feat: add orderbook shadow training pipeline

This commit is contained in:
Курнат Андрей
2026-07-15 09:44:29 +03:00
parent f7a625586e
commit 5d8ad1437e
19 changed files with 1486 additions and 23 deletions
+2 -2
View File
@@ -10,8 +10,8 @@ android {
applicationId = "xyz.kusoft.tradebotmonitor"
minSdk = 26
targetSdk = 37
versionCode = 23
versionName = "0.5.1"
versionCode = 24
versionName = "0.5.2"
}
}
@@ -1104,6 +1104,8 @@ class MainActivity : Activity() {
addView(trainingComputerPanel(retrain).top(dp(12)))
addView(thinDivider().top(dp(12)))
addView(trainingProcessPanel(coordination))
addView(orderbookStagePanel(coordination).top(dp(10)))
addView(shadowStagePanel(retrain.optJSONObject("shadow") ?: JSONObject()).top(dp(10)))
if (displayedEvaluation.optJSONObject("candidate") != null) {
addView(guardSummaryPanel(displayedEvaluation).top(dp(10)))
}
@@ -1155,6 +1157,36 @@ class MainActivity : Activity() {
}
}
private fun orderbookStagePanel(coordination: JSONObject): View =
LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
val summary = coordination.optJSONObject("latest_job")?.optJSONObject("summary") ?: JSONObject()
val state = summary.optStringClean("state")
val minimum = summary.optInt("minimum_covered_buckets", 240)
val eligible = summary.optInt("eligible_symbol_count", 0)
val requiredSymbols = summary.optInt("minimum_symbols", 2)
val coverage = summary.optJSONObject("covered_buckets_by_symbol") ?: JSONObject()
val bestCoverage = coverage.keys().asSequence().map { coverage.optInt(it, 0) }.maxOrNull() ?: 0
addView(keyValueLine("Forward-стакан", if (state == "ready") "готов к обучению" else "накапливается", if (state == "ready") palette.green else palette.amber))
addView(keyValueLine("Лучшее покрытие", "$bestCoverage / $minimum свечей").top(dp(4)))
addView(keyValueLine("Готовые пары", "$eligible / $requiredSymbols").top(dp(4)))
}
private fun shadowStagePanel(shadow: JSONObject): View =
LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
val state = shadow.optStringClean("state").ifBlank { "нет модели" }
val color = when (state) {
"passed" -> palette.green
"failed" -> palette.red
else -> palette.amber
}
addView(keyValueLine("Shadow gate", state, color))
addView(keyValueLine("Forward-прогнозы", "${shadow.optInt("settled_predictions", 0)} / ${shadow.optInt("total_predictions", 0)}").top(dp(4)))
addView(keyValueLine("Shadow P&L", signedPercent(shadow.optDouble("total_net_percent", 0.0)), colorForSigned(shadow.optDouble("total_net_percent", 0.0))).top(dp(4)))
addView(keyValueLine("Direction / Brier", "${percent(shadow.optDouble("direction_accuracy", 0.0) * 100.0, 1)} / ${number(shadow.optDouble("brier", 0.0), 4)}").top(dp(4)))
}
private fun guardSummaryPanel(retrain: JSONObject): View =
LinearLayout(this).apply {
val accepted = retrain.optBoolean("accepted", false)