启用概率校准和 WebSocket 报价配置
This commit is contained in:
@@ -177,6 +177,11 @@ POLYMARKET_CHAIN_ID=137
|
|||||||
POLYMARKET_HTTP_TIMEOUT_SEC=8
|
POLYMARKET_HTTP_TIMEOUT_SEC=8
|
||||||
POLYMARKET_MARKET_CACHE_TTL_SEC=180
|
POLYMARKET_MARKET_CACHE_TTL_SEC=180
|
||||||
POLYMARKET_PRICE_CACHE_TTL_SEC=10
|
POLYMARKET_PRICE_CACHE_TTL_SEC=10
|
||||||
|
POLYMARKET_WS_PRICE_ENABLED=false
|
||||||
|
POLYMARKET_WS_MARKET_URL=wss://ws-subscriptions-clob.polymarket.com/ws/market
|
||||||
|
POLYMARKET_WS_QUOTE_TTL_SEC=8
|
||||||
|
POLYMARKET_WS_MAX_ASSETS=256
|
||||||
|
POLYMARKET_WS_RECONNECT_DELAY_SEC=3
|
||||||
POLYMARKET_DISCOVERY_PAGES=6
|
POLYMARKET_DISCOVERY_PAGES=6
|
||||||
POLYMARKET_DISCOVERY_LIMIT=200
|
POLYMARKET_DISCOVERY_LIMIT=200
|
||||||
POLYMARKET_SIGNAL_MIN_LIQUIDITY=500
|
POLYMARKET_SIGNAL_MIN_LIQUIDITY=500
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"ok": true,
|
"ok": true,
|
||||||
"version": "emos-auto-20260418212046",
|
"version": "emos-auto-20260421122743",
|
||||||
"generated_at": "2026-04-18T21:21:04.160748+00:00",
|
"generated_at": "2026-04-21T12:28:08.021388+00:00",
|
||||||
"candidate_dir": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260418212046",
|
"candidate_dir": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743",
|
||||||
"candidate_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260418212046\\default.json",
|
"candidate_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json",
|
||||||
"evaluation_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260418212046\\evaluation_report.json",
|
"evaluation_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\evaluation_report.json",
|
||||||
"target_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.json",
|
"target_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.json",
|
||||||
"promote_requested": false,
|
"promote_requested": true,
|
||||||
"promoted": false,
|
"promoted": true,
|
||||||
"backup_path": null,
|
"backup_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.backup-20260421122808.json",
|
||||||
"decision": {
|
"decision": {
|
||||||
"decision": "promote",
|
"decision": "promote",
|
||||||
"ready_for_promotion": true,
|
"ready_for_promotion": true,
|
||||||
@@ -20,10 +20,10 @@
|
|||||||
"min_delta_bucket_hit_rate": -0.05
|
"min_delta_bucket_hit_rate": -0.05
|
||||||
},
|
},
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"sample_count": 847,
|
"sample_count": 978,
|
||||||
"delta_crps": -0.03617,
|
"delta_crps": -0.05721,
|
||||||
"delta_mae": -0.007896,
|
"delta_mae": -0.034568,
|
||||||
"delta_bucket_hit_rate": -0.009445
|
"delta_bucket_hit_rate": -0.00409
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fit": {
|
"fit": {
|
||||||
@@ -31,9 +31,9 @@
|
|||||||
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
"scripts/fit_probability_calibration.py",
|
"scripts/fit_probability_calibration.py",
|
||||||
"--output",
|
"--output",
|
||||||
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260418212046\\default.json",
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json",
|
||||||
"--version",
|
"--version",
|
||||||
"emos-auto-20260418212046",
|
"emos-auto-20260421122743",
|
||||||
"--verbose",
|
"--verbose",
|
||||||
"--snapshot-limit",
|
"--snapshot-limit",
|
||||||
"50000"
|
"50000"
|
||||||
@@ -47,9 +47,9 @@
|
|||||||
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
"scripts/evaluate_probability_calibration.py",
|
"scripts/evaluate_probability_calibration.py",
|
||||||
"--calibration-file",
|
"--calibration-file",
|
||||||
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260418212046\\default.json",
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json",
|
||||||
"--output",
|
"--output",
|
||||||
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260418212046\\evaluation_report.json",
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\evaluation_report.json",
|
||||||
"--verbose",
|
"--verbose",
|
||||||
"--snapshot-limit",
|
"--snapshot-limit",
|
||||||
"50000"
|
"50000"
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"version": "emos-auto-20260421115828",
|
||||||
|
"generated_at": "2026-04-21T11:58:32.490537+00:00",
|
||||||
|
"candidate_dir": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828",
|
||||||
|
"candidate_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828\\default.json",
|
||||||
|
"evaluation_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828\\evaluation_report.json",
|
||||||
|
"target_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.json",
|
||||||
|
"promote_requested": false,
|
||||||
|
"promoted": false,
|
||||||
|
"backup_path": null,
|
||||||
|
"decision": {
|
||||||
|
"decision": "promote",
|
||||||
|
"ready_for_promotion": true,
|
||||||
|
"blocking_reasons": [],
|
||||||
|
"thresholds": {
|
||||||
|
"min_samples": 50,
|
||||||
|
"max_delta_crps": 0.0,
|
||||||
|
"max_delta_mae": 0.05,
|
||||||
|
"min_delta_bucket_hit_rate": -0.05
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 74,
|
||||||
|
"delta_crps": -0.142868,
|
||||||
|
"delta_mae": -0.056741,
|
||||||
|
"delta_bucket_hit_rate": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fit": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/fit_probability_calibration.py",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828\\default.json",
|
||||||
|
"--version",
|
||||||
|
"emos-auto-20260421115828",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 0,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
},
|
||||||
|
"evaluate": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/evaluate_probability_calibration.py",
|
||||||
|
"--calibration-file",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828\\default.json",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828\\evaluation_report.json",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 0,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
},
|
||||||
|
"tests": null
|
||||||
|
}
|
||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"version": "emos-auto-20260421115828",
|
||||||
|
"trained_at": "2026-04-21T11:58:31.424860+00:00",
|
||||||
|
"global": {
|
||||||
|
"mu": {
|
||||||
|
"intercept": 2.60074353,
|
||||||
|
"raw_mu_coef": 1.97765258,
|
||||||
|
"deb_coef": -1.37457626,
|
||||||
|
"ens_median_coef": 0.10693472,
|
||||||
|
"max_so_far_gap_coef": -0.58256593
|
||||||
|
},
|
||||||
|
"sigma": {
|
||||||
|
"intercept": 0.6373609,
|
||||||
|
"raw_sigma_coef": -1.41537225,
|
||||||
|
"spread_coef": 2.12997577,
|
||||||
|
"peak_flag_coef": -0.08633203,
|
||||||
|
"max_so_far_gap_coef": -0.00716383
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sigma_constraints": {
|
||||||
|
"min_ratio": 0.85,
|
||||||
|
"max_ratio": 1.35,
|
||||||
|
"absolute_min": 0.25,
|
||||||
|
"absolute_max": 3.0
|
||||||
|
},
|
||||||
|
"selection_guardrails": {
|
||||||
|
"max_mae_increase": 0.02,
|
||||||
|
"max_bucket_hit_drop": 0.01,
|
||||||
|
"max_bucket_brier_increase": 0.05
|
||||||
|
},
|
||||||
|
"blending": {
|
||||||
|
"alpha_mu": 0.05,
|
||||||
|
"alpha_sigma": 0.7
|
||||||
|
},
|
||||||
|
"cities": {
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": 2.101101,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"ankara": {
|
||||||
|
"samples": 6,
|
||||||
|
"mu_bias": -0.523145,
|
||||||
|
"sigma_scale": 1.139849,
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -0.285183,
|
||||||
|
"sigma_scale": 0.550171,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 7,
|
||||||
|
"mu_bias": 3.234676,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.875
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": 4.731246,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": 0.177772,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -3.070325,
|
||||||
|
"sigma_scale": 1.462196,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -4.249866,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": 1.080039,
|
||||||
|
"sigma_scale": 1.638119,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -1.68611,
|
||||||
|
"sigma_scale": 1.38114,
|
||||||
|
"confidence": 0.375
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 74,
|
||||||
|
"mean_crps": 3.181501,
|
||||||
|
"legacy_mean_crps": 3.474108,
|
||||||
|
"legacy_mean_mae": 3.679324,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"legacy_bucket_brier": 0.855395,
|
||||||
|
"selected_mean_crps": 3.322469,
|
||||||
|
"selected_mean_mae": 3.618254,
|
||||||
|
"selected_bucket_hit_rate": 0.5,
|
||||||
|
"selected_bucket_brier": 0.863048,
|
||||||
|
"selected_score": 5.08158,
|
||||||
|
"legacy_score": 5.233586,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"settlement_history_city_count": 30,
|
||||||
|
"legacy_archive_samples": 54
|
||||||
|
},
|
||||||
|
"source": "artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421115828\\default.json"
|
||||||
|
}
|
||||||
+293
@@ -0,0 +1,293 @@
|
|||||||
|
{
|
||||||
|
"summary": {
|
||||||
|
"sample_count": 74,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"legacy": {
|
||||||
|
"mean_crps": 3.474108,
|
||||||
|
"mean_mae": 3.679324,
|
||||||
|
"bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"emos": {
|
||||||
|
"mean_crps": 3.33124,
|
||||||
|
"mean_mae": 3.622584,
|
||||||
|
"bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"delta": {
|
||||||
|
"crps": -0.142868,
|
||||||
|
"mae": -0.056741,
|
||||||
|
"bucket_hit_rate": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"by_city": {
|
||||||
|
"ankara": {
|
||||||
|
"samples": 6,
|
||||||
|
"legacy_mean_crps": 1.365135,
|
||||||
|
"emos_mean_crps": 1.392829,
|
||||||
|
"legacy_mean_mae": 1.466667,
|
||||||
|
"emos_mean_mae": 1.444819,
|
||||||
|
"legacy_bucket_hit_rate": 0.666667,
|
||||||
|
"emos_bucket_hit_rate": 0.666667
|
||||||
|
},
|
||||||
|
"atlanta": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 30.449382,
|
||||||
|
"emos_mean_crps": 29.886236,
|
||||||
|
"legacy_mean_mae": 32.015,
|
||||||
|
"emos_mean_mae": 31.322804,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"buenos aires": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 9.113412,
|
||||||
|
"emos_mean_crps": 8.463522,
|
||||||
|
"legacy_mean_mae": 10.27,
|
||||||
|
"emos_mean_mae": 10.024533,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 3,
|
||||||
|
"legacy_mean_crps": 0.276202,
|
||||||
|
"emos_mean_crps": 0.326485,
|
||||||
|
"legacy_mean_mae": 0.3,
|
||||||
|
"emos_mean_mae": 0.239636,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"chengdu": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 0.306469,
|
||||||
|
"emos_mean_crps": 0.378812,
|
||||||
|
"legacy_mean_mae": 0.3,
|
||||||
|
"emos_mean_mae": 0.153224,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"chicago": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 1.250268,
|
||||||
|
"emos_mean_crps": 0.714669,
|
||||||
|
"legacy_mean_mae": 0.0,
|
||||||
|
"emos_mean_mae": 0.319756,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"dallas": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 2.173363,
|
||||||
|
"emos_mean_crps": 0.840297,
|
||||||
|
"legacy_mean_mae": 0.0,
|
||||||
|
"emos_mean_mae": 1.028146,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 7,
|
||||||
|
"legacy_mean_crps": 0.706099,
|
||||||
|
"emos_mean_crps": 0.731926,
|
||||||
|
"legacy_mean_mae": 0.657143,
|
||||||
|
"emos_mean_mae": 0.669911,
|
||||||
|
"legacy_bucket_hit_rate": 0.714286,
|
||||||
|
"emos_bucket_hit_rate": 0.571429
|
||||||
|
},
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 3,
|
||||||
|
"legacy_mean_crps": 1.264103,
|
||||||
|
"emos_mean_crps": 1.214967,
|
||||||
|
"legacy_mean_mae": 1.5,
|
||||||
|
"emos_mean_mae": 1.469837,
|
||||||
|
"legacy_bucket_hit_rate": 0.333333,
|
||||||
|
"emos_bucket_hit_rate": 0.666667
|
||||||
|
},
|
||||||
|
"london": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 3.885033,
|
||||||
|
"emos_mean_crps": 3.799841,
|
||||||
|
"legacy_mean_mae": 4.135,
|
||||||
|
"emos_mean_mae": 4.027503,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"lucknow": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 2.487193,
|
||||||
|
"emos_mean_crps": 2.107441,
|
||||||
|
"legacy_mean_mae": 3.205,
|
||||||
|
"emos_mean_mae": 2.876943,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"madrid": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 6.27726,
|
||||||
|
"emos_mean_crps": 5.810228,
|
||||||
|
"legacy_mean_mae": 7.33,
|
||||||
|
"emos_mean_mae": 7.195133,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"miami": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 28.637631,
|
||||||
|
"emos_mean_crps": 27.592664,
|
||||||
|
"legacy_mean_mae": 30.175,
|
||||||
|
"emos_mean_mae": 29.284979,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 3,
|
||||||
|
"legacy_mean_crps": 4.401392,
|
||||||
|
"emos_mean_crps": 3.782613,
|
||||||
|
"legacy_mean_mae": 4.06,
|
||||||
|
"emos_mean_mae": 3.989808,
|
||||||
|
"legacy_bucket_hit_rate": 0.666667,
|
||||||
|
"emos_bucket_hit_rate": 0.666667
|
||||||
|
},
|
||||||
|
"munich": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 3.145192,
|
||||||
|
"emos_mean_crps": 2.990712,
|
||||||
|
"legacy_mean_mae": 3.64,
|
||||||
|
"emos_mean_mae": 3.61502,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"new york": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 3.692845,
|
||||||
|
"emos_mean_crps": 3.021798,
|
||||||
|
"legacy_mean_mae": 4.94,
|
||||||
|
"emos_mean_mae": 4.54437,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"paris": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 4.013782,
|
||||||
|
"emos_mean_crps": 3.915303,
|
||||||
|
"legacy_mean_mae": 4.265,
|
||||||
|
"emos_mean_mae": 4.179694,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"sao paulo": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 5.540967,
|
||||||
|
"emos_mean_crps": 5.018605,
|
||||||
|
"legacy_mean_mae": 6.57,
|
||||||
|
"emos_mean_mae": 6.314389,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"seattle": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 0.315488,
|
||||||
|
"emos_mean_crps": 0.524119,
|
||||||
|
"legacy_mean_mae": 0.0,
|
||||||
|
"emos_mean_mae": 0.673609,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 3,
|
||||||
|
"legacy_mean_crps": 0.508331,
|
||||||
|
"emos_mean_crps": 0.520762,
|
||||||
|
"legacy_mean_mae": 0.2,
|
||||||
|
"emos_mean_mae": 0.247862,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 3,
|
||||||
|
"legacy_mean_crps": 0.299116,
|
||||||
|
"emos_mean_crps": 0.402453,
|
||||||
|
"legacy_mean_mae": 0.1,
|
||||||
|
"emos_mean_mae": 0.189437,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"shenzhen": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 1.198351,
|
||||||
|
"emos_mean_crps": 1.490963,
|
||||||
|
"legacy_mean_mae": 1.3,
|
||||||
|
"emos_mean_mae": 1.628189,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"singapore": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 0.281993,
|
||||||
|
"emos_mean_crps": 0.370374,
|
||||||
|
"legacy_mean_mae": 0.15,
|
||||||
|
"emos_mean_mae": 0.118005,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 5,
|
||||||
|
"legacy_mean_crps": 0.950739,
|
||||||
|
"emos_mean_crps": 1.042332,
|
||||||
|
"legacy_mean_mae": 0.94,
|
||||||
|
"emos_mean_mae": 0.951241,
|
||||||
|
"legacy_bucket_hit_rate": 0.6,
|
||||||
|
"emos_bucket_hit_rate": 0.6
|
||||||
|
},
|
||||||
|
"tel aviv": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 0.446758,
|
||||||
|
"emos_mean_crps": 0.578691,
|
||||||
|
"legacy_mean_mae": 0.3,
|
||||||
|
"emos_mean_mae": 0.116966,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 5,
|
||||||
|
"legacy_mean_crps": 0.879366,
|
||||||
|
"emos_mean_crps": 0.876608,
|
||||||
|
"legacy_mean_mae": 1.022,
|
||||||
|
"emos_mean_mae": 1.008317,
|
||||||
|
"legacy_bucket_hit_rate": 0.2,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"toronto": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 5.497916,
|
||||||
|
"emos_mean_crps": 5.268783,
|
||||||
|
"legacy_mean_mae": 6.33,
|
||||||
|
"emos_mean_mae": 6.388522,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 3,
|
||||||
|
"legacy_mean_crps": 1.618875,
|
||||||
|
"emos_mean_crps": 1.524219,
|
||||||
|
"legacy_mean_mae": 2.056667,
|
||||||
|
"emos_mean_mae": 2.006524,
|
||||||
|
"legacy_bucket_hit_rate": 0.333333,
|
||||||
|
"emos_bucket_hit_rate": 0.333333
|
||||||
|
},
|
||||||
|
"wellington": {
|
||||||
|
"samples": 2,
|
||||||
|
"legacy_mean_crps": 0.364919,
|
||||||
|
"emos_mean_crps": 0.484124,
|
||||||
|
"legacy_mean_mae": 0.15,
|
||||||
|
"emos_mean_mae": 0.123335,
|
||||||
|
"legacy_bucket_hit_rate": 1.0,
|
||||||
|
"emos_bucket_hit_rate": 1.0
|
||||||
|
},
|
||||||
|
"wuhan": {
|
||||||
|
"samples": 1,
|
||||||
|
"legacy_mean_crps": 0.476225,
|
||||||
|
"emos_mean_crps": 0.578405,
|
||||||
|
"legacy_mean_mae": 0.8,
|
||||||
|
"emos_mean_mae": 0.962852,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"ok": false,
|
||||||
|
"version": "emos-auto-20260421121159",
|
||||||
|
"stage": "fit",
|
||||||
|
"fit": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/fit_probability_calibration.py",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121159\\default.json",
|
||||||
|
"--version",
|
||||||
|
"emos-auto-20260421121159",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 1,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"version": "emos-auto-20260421121920",
|
||||||
|
"generated_at": "2026-04-21T12:19:41.596944+00:00",
|
||||||
|
"candidate_dir": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920",
|
||||||
|
"candidate_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920\\default.json",
|
||||||
|
"evaluation_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920\\evaluation_report.json",
|
||||||
|
"target_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.json",
|
||||||
|
"promote_requested": false,
|
||||||
|
"promoted": false,
|
||||||
|
"backup_path": null,
|
||||||
|
"decision": {
|
||||||
|
"decision": "promote",
|
||||||
|
"ready_for_promotion": true,
|
||||||
|
"blocking_reasons": [],
|
||||||
|
"thresholds": {
|
||||||
|
"min_samples": 50,
|
||||||
|
"max_delta_crps": 0.0,
|
||||||
|
"max_delta_mae": 0.05,
|
||||||
|
"min_delta_bucket_hit_rate": -0.05
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 978,
|
||||||
|
"delta_crps": -0.05721,
|
||||||
|
"delta_mae": -0.034568,
|
||||||
|
"delta_bucket_hit_rate": -0.00409
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fit": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/fit_probability_calibration.py",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920\\default.json",
|
||||||
|
"--version",
|
||||||
|
"emos-auto-20260421121920",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 0,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
},
|
||||||
|
"evaluate": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/evaluate_probability_calibration.py",
|
||||||
|
"--calibration-file",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920\\default.json",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920\\evaluation_report.json",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 0,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
},
|
||||||
|
"tests": null
|
||||||
|
}
|
||||||
+361
@@ -0,0 +1,361 @@
|
|||||||
|
{
|
||||||
|
"version": "emos-auto-20260421121920",
|
||||||
|
"trained_at": "2026-04-21T12:19:38.887631+00:00",
|
||||||
|
"global": {
|
||||||
|
"mu": {
|
||||||
|
"intercept": 0.34330438,
|
||||||
|
"raw_mu_coef": 0.48749629,
|
||||||
|
"deb_coef": 0.45733479,
|
||||||
|
"ens_median_coef": 0.05955297,
|
||||||
|
"max_so_far_gap_coef": -0.104935
|
||||||
|
},
|
||||||
|
"sigma": {
|
||||||
|
"intercept": -0.62765582,
|
||||||
|
"raw_sigma_coef": 0.38492261,
|
||||||
|
"spread_coef": 0.29095921,
|
||||||
|
"peak_flag_coef": 0.33966327,
|
||||||
|
"max_so_far_gap_coef": 0.08357376
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sigma_constraints": {
|
||||||
|
"min_ratio": 0.85,
|
||||||
|
"max_ratio": 1.35,
|
||||||
|
"absolute_min": 0.25,
|
||||||
|
"absolute_max": 3.0
|
||||||
|
},
|
||||||
|
"selection_guardrails": {
|
||||||
|
"max_mae_increase": 0.02,
|
||||||
|
"max_bucket_hit_drop": 0.01,
|
||||||
|
"max_bucket_brier_increase": 0.05
|
||||||
|
},
|
||||||
|
"blending": {
|
||||||
|
"alpha_mu": 0.25,
|
||||||
|
"alpha_sigma": 1.0
|
||||||
|
},
|
||||||
|
"cities": {
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.438949,
|
||||||
|
"sigma_scale": 0.553793,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"buenos aires": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -1.044971,
|
||||||
|
"sigma_scale": 1.389753,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"ankara": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.067406,
|
||||||
|
"sigma_scale": 1.270298,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"london": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.010833,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"paris": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.21677,
|
||||||
|
"sigma_scale": 1.095669,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"new york": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 1.072189,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"lagos": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": -0.092732,
|
||||||
|
"sigma_scale": 1.558646,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"madrid": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.627862,
|
||||||
|
"sigma_scale": 1.761239,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"toronto": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.424101,
|
||||||
|
"sigma_scale": 1.326675,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"wellington": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.347796,
|
||||||
|
"sigma_scale": 0.893459,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"los angeles": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.659983,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"san francisco": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.941818,
|
||||||
|
"sigma_scale": 1.979403,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"aurora": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 2.040009,
|
||||||
|
"sigma_scale": 0.982492,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"austin": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.990023,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"houston": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.188787,
|
||||||
|
"sigma_scale": 1.819594,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chicago": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 2.285098,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"dallas": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 0.258095,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"atlanta": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -2.093105,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"seattle": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": -0.982188,
|
||||||
|
"sigma_scale": 1.695172,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"sao paulo": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.786242,
|
||||||
|
"sigma_scale": 1.427037,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"munich": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.096559,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": -0.045038,
|
||||||
|
"sigma_scale": 1.626331,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": -0.50853,
|
||||||
|
"sigma_scale": 1.239146,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"helsinki": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": 0.442247,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"amsterdam": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": 0.129889,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"panama city": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": -0.040792,
|
||||||
|
"sigma_scale": 1.393259,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"cape town": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": 0.507293,
|
||||||
|
"sigma_scale": 1.420004,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"miami": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -2.736316,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"manila": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": 1.772229,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"singapore": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.289639,
|
||||||
|
"sigma_scale": 1.124006,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.332129,
|
||||||
|
"sigma_scale": 0.729483,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 1.6533,
|
||||||
|
"sigma_scale": 0.82648,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.343239,
|
||||||
|
"sigma_scale": 1.886868,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"mexico city": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.087122,
|
||||||
|
"sigma_scale": 1.108884,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.348022,
|
||||||
|
"sigma_scale": 0.810527,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"beijing": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.288176,
|
||||||
|
"sigma_scale": 0.952972,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"shenzhen": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": -0.006114,
|
||||||
|
"sigma_scale": 0.728494,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"wuhan": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.771154,
|
||||||
|
"sigma_scale": 1.30329,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chengdu": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.445906,
|
||||||
|
"sigma_scale": 0.796989,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chongqing": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.021301,
|
||||||
|
"sigma_scale": 1.106566,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 24,
|
||||||
|
"mu_bias": 0.37527,
|
||||||
|
"sigma_scale": 0.517756,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.600671,
|
||||||
|
"sigma_scale": 0.5,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"guangzhou": {
|
||||||
|
"samples": 6,
|
||||||
|
"mu_bias": 0.7082,
|
||||||
|
"sigma_scale": 1.975103,
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
"lau fau shan": {
|
||||||
|
"samples": 19,
|
||||||
|
"mu_bias": 0.41371,
|
||||||
|
"sigma_scale": 0.656578,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"kuala lumpur": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.499197,
|
||||||
|
"sigma_scale": 1.361171,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"jakarta": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.293537,
|
||||||
|
"sigma_scale": 0.751498,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"lucknow": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -1.593437,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"karachi": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": -0.035595,
|
||||||
|
"sigma_scale": 0.588612,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"jeddah": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": 0.516879,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"moscow": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.609602,
|
||||||
|
"sigma_scale": 0.783723,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"tel aviv": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.436837,
|
||||||
|
"sigma_scale": 1.46524,
|
||||||
|
"confidence": 1.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 978,
|
||||||
|
"mean_crps": 1.330733,
|
||||||
|
"legacy_mean_crps": 1.376936,
|
||||||
|
"legacy_mean_mae": 1.589438,
|
||||||
|
"legacy_bucket_hit_rate": 0.43865,
|
||||||
|
"legacy_bucket_brier": 0.824571,
|
||||||
|
"selected_mean_crps": 1.311763,
|
||||||
|
"selected_mean_mae": 1.553658,
|
||||||
|
"selected_bucket_hit_rate": 0.432515,
|
||||||
|
"selected_bucket_brier": 0.789817,
|
||||||
|
"selected_score": 2.910718,
|
||||||
|
"legacy_score": 2.996333,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"settlement_history_city_count": 30,
|
||||||
|
"legacy_archive_samples": 54
|
||||||
|
},
|
||||||
|
"source": "artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421121920\\default.json"
|
||||||
|
}
|
||||||
+482
@@ -0,0 +1,482 @@
|
|||||||
|
{
|
||||||
|
"summary": {
|
||||||
|
"sample_count": 978,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"legacy": {
|
||||||
|
"mean_crps": 1.376936,
|
||||||
|
"mean_mae": 1.589438,
|
||||||
|
"bucket_hit_rate": 0.43865
|
||||||
|
},
|
||||||
|
"emos": {
|
||||||
|
"mean_crps": 1.319727,
|
||||||
|
"mean_mae": 1.554869,
|
||||||
|
"bucket_hit_rate": 0.43456
|
||||||
|
},
|
||||||
|
"delta": {
|
||||||
|
"crps": -0.05721,
|
||||||
|
"mae": -0.034568,
|
||||||
|
"bucket_hit_rate": -0.00409
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"by_city": {
|
||||||
|
"amsterdam": {
|
||||||
|
"samples": 17,
|
||||||
|
"legacy_mean_crps": 0.868937,
|
||||||
|
"emos_mean_crps": 0.847633,
|
||||||
|
"legacy_mean_mae": 0.983529,
|
||||||
|
"emos_mean_mae": 0.979456,
|
||||||
|
"legacy_bucket_hit_rate": 0.529412,
|
||||||
|
"emos_bucket_hit_rate": 0.470588
|
||||||
|
},
|
||||||
|
"ankara": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 0.610138,
|
||||||
|
"emos_mean_crps": 0.569029,
|
||||||
|
"legacy_mean_mae": 0.726087,
|
||||||
|
"emos_mean_mae": 0.731312,
|
||||||
|
"legacy_bucket_hit_rate": 0.434783,
|
||||||
|
"emos_bucket_hit_rate": 0.391304
|
||||||
|
},
|
||||||
|
"atlanta": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 4.304444,
|
||||||
|
"emos_mean_crps": 4.435438,
|
||||||
|
"legacy_mean_mae": 4.79,
|
||||||
|
"emos_mean_mae": 4.992948,
|
||||||
|
"legacy_bucket_hit_rate": 0.181818,
|
||||||
|
"emos_bucket_hit_rate": 0.090909
|
||||||
|
},
|
||||||
|
"aurora": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 3.989577,
|
||||||
|
"emos_mean_crps": 3.688746,
|
||||||
|
"legacy_mean_mae": 4.5115,
|
||||||
|
"emos_mean_mae": 4.454993,
|
||||||
|
"legacy_bucket_hit_rate": 0.1,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"austin": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 2.261424,
|
||||||
|
"emos_mean_crps": 2.109386,
|
||||||
|
"legacy_mean_mae": 2.422,
|
||||||
|
"emos_mean_mae": 2.377675,
|
||||||
|
"legacy_bucket_hit_rate": 0.45,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"beijing": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.116518,
|
||||||
|
"emos_mean_crps": 1.123144,
|
||||||
|
"legacy_mean_mae": 1.4955,
|
||||||
|
"emos_mean_mae": 1.468371,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"buenos aires": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.632274,
|
||||||
|
"emos_mean_crps": 1.657172,
|
||||||
|
"legacy_mean_mae": 1.885,
|
||||||
|
"emos_mean_mae": 1.875542,
|
||||||
|
"legacy_bucket_hit_rate": 0.454545,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 16,
|
||||||
|
"legacy_mean_crps": 1.066146,
|
||||||
|
"emos_mean_crps": 0.99263,
|
||||||
|
"legacy_mean_mae": 1.304375,
|
||||||
|
"emos_mean_mae": 1.259453,
|
||||||
|
"legacy_bucket_hit_rate": 0.375,
|
||||||
|
"emos_bucket_hit_rate": 0.375
|
||||||
|
},
|
||||||
|
"cape town": {
|
||||||
|
"samples": 10,
|
||||||
|
"legacy_mean_crps": 0.7369,
|
||||||
|
"emos_mean_crps": 0.646728,
|
||||||
|
"legacy_mean_mae": 0.882,
|
||||||
|
"emos_mean_mae": 0.809407,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"chengdu": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.009046,
|
||||||
|
"emos_mean_crps": 0.964076,
|
||||||
|
"legacy_mean_mae": 1.1835,
|
||||||
|
"emos_mean_mae": 1.155294,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"chicago": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 3.052956,
|
||||||
|
"emos_mean_crps": 2.842851,
|
||||||
|
"legacy_mean_mae": 3.398095,
|
||||||
|
"emos_mean_mae": 3.312975,
|
||||||
|
"legacy_bucket_hit_rate": 0.285714,
|
||||||
|
"emos_bucket_hit_rate": 0.095238
|
||||||
|
},
|
||||||
|
"chongqing": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.239078,
|
||||||
|
"emos_mean_crps": 1.231804,
|
||||||
|
"legacy_mean_mae": 1.4955,
|
||||||
|
"emos_mean_mae": 1.501486,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"dallas": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 1.795116,
|
||||||
|
"emos_mean_crps": 1.700865,
|
||||||
|
"legacy_mean_mae": 1.979048,
|
||||||
|
"emos_mean_mae": 2.017151,
|
||||||
|
"legacy_bucket_hit_rate": 0.285714,
|
||||||
|
"emos_bucket_hit_rate": 0.238095
|
||||||
|
},
|
||||||
|
"guangzhou": {
|
||||||
|
"samples": 6,
|
||||||
|
"legacy_mean_crps": 1.586654,
|
||||||
|
"emos_mean_crps": 1.565936,
|
||||||
|
"legacy_mean_mae": 1.991667,
|
||||||
|
"emos_mean_mae": 1.995792,
|
||||||
|
"legacy_bucket_hit_rate": 0.166667,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"helsinki": {
|
||||||
|
"samples": 17,
|
||||||
|
"legacy_mean_crps": 0.626777,
|
||||||
|
"emos_mean_crps": 0.489382,
|
||||||
|
"legacy_mean_mae": 0.785294,
|
||||||
|
"emos_mean_mae": 0.640606,
|
||||||
|
"legacy_bucket_hit_rate": 0.470588,
|
||||||
|
"emos_bucket_hit_rate": 0.529412
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 24,
|
||||||
|
"legacy_mean_crps": 0.531004,
|
||||||
|
"emos_mean_crps": 0.473302,
|
||||||
|
"legacy_mean_mae": 0.552917,
|
||||||
|
"emos_mean_mae": 0.52881,
|
||||||
|
"legacy_bucket_hit_rate": 0.666667,
|
||||||
|
"emos_bucket_hit_rate": 0.75
|
||||||
|
},
|
||||||
|
"houston": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.488859,
|
||||||
|
"emos_mean_crps": 1.412564,
|
||||||
|
"legacy_mean_mae": 1.8085,
|
||||||
|
"emos_mean_mae": 1.80359,
|
||||||
|
"legacy_bucket_hit_rate": 0.25,
|
||||||
|
"emos_bucket_hit_rate": 0.2
|
||||||
|
},
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.586067,
|
||||||
|
"emos_mean_crps": 0.546494,
|
||||||
|
"legacy_mean_mae": 0.6225,
|
||||||
|
"emos_mean_mae": 0.557255,
|
||||||
|
"legacy_bucket_hit_rate": 0.7,
|
||||||
|
"emos_bucket_hit_rate": 0.7
|
||||||
|
},
|
||||||
|
"jakarta": {
|
||||||
|
"samples": 16,
|
||||||
|
"legacy_mean_crps": 0.620583,
|
||||||
|
"emos_mean_crps": 0.553084,
|
||||||
|
"legacy_mean_mae": 0.875625,
|
||||||
|
"emos_mean_mae": 0.793719,
|
||||||
|
"legacy_bucket_hit_rate": 0.4375,
|
||||||
|
"emos_bucket_hit_rate": 0.4375
|
||||||
|
},
|
||||||
|
"jeddah": {
|
||||||
|
"samples": 10,
|
||||||
|
"legacy_mean_crps": 1.822658,
|
||||||
|
"emos_mean_crps": 1.674198,
|
||||||
|
"legacy_mean_mae": 2.277,
|
||||||
|
"emos_mean_mae": 2.192556,
|
||||||
|
"legacy_bucket_hit_rate": 0.2,
|
||||||
|
"emos_bucket_hit_rate": 0.1
|
||||||
|
},
|
||||||
|
"karachi": {
|
||||||
|
"samples": 5,
|
||||||
|
"legacy_mean_crps": 0.361328,
|
||||||
|
"emos_mean_crps": 0.326866,
|
||||||
|
"legacy_mean_mae": 0.398,
|
||||||
|
"emos_mean_mae": 0.336276,
|
||||||
|
"legacy_bucket_hit_rate": 0.8,
|
||||||
|
"emos_bucket_hit_rate": 0.8
|
||||||
|
},
|
||||||
|
"kuala lumpur": {
|
||||||
|
"samples": 16,
|
||||||
|
"legacy_mean_crps": 0.927888,
|
||||||
|
"emos_mean_crps": 0.86633,
|
||||||
|
"legacy_mean_mae": 1.146875,
|
||||||
|
"emos_mean_mae": 1.083193,
|
||||||
|
"legacy_bucket_hit_rate": 0.375,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"lagos": {
|
||||||
|
"samples": 10,
|
||||||
|
"legacy_mean_crps": 1.174893,
|
||||||
|
"emos_mean_crps": 1.204827,
|
||||||
|
"legacy_mean_mae": 1.592,
|
||||||
|
"emos_mean_mae": 1.586221,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"lau fau shan": {
|
||||||
|
"samples": 19,
|
||||||
|
"legacy_mean_crps": 0.713018,
|
||||||
|
"emos_mean_crps": 0.63244,
|
||||||
|
"legacy_mean_mae": 0.706316,
|
||||||
|
"emos_mean_mae": 0.641667,
|
||||||
|
"legacy_bucket_hit_rate": 0.578947,
|
||||||
|
"emos_bucket_hit_rate": 0.578947
|
||||||
|
},
|
||||||
|
"london": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.298133,
|
||||||
|
"emos_mean_crps": 1.267504,
|
||||||
|
"legacy_mean_mae": 1.429091,
|
||||||
|
"emos_mean_mae": 1.422989,
|
||||||
|
"legacy_bucket_hit_rate": 0.409091,
|
||||||
|
"emos_bucket_hit_rate": 0.409091
|
||||||
|
},
|
||||||
|
"los angeles": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 2.051516,
|
||||||
|
"emos_mean_crps": 2.006381,
|
||||||
|
"legacy_mean_mae": 2.4145,
|
||||||
|
"emos_mean_mae": 2.366065,
|
||||||
|
"legacy_bucket_hit_rate": 0.3,
|
||||||
|
"emos_bucket_hit_rate": 0.3
|
||||||
|
},
|
||||||
|
"lucknow": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.134917,
|
||||||
|
"emos_mean_crps": 0.890494,
|
||||||
|
"legacy_mean_mae": 1.532727,
|
||||||
|
"emos_mean_mae": 1.201547,
|
||||||
|
"legacy_bucket_hit_rate": 0.136364,
|
||||||
|
"emos_bucket_hit_rate": 0.272727
|
||||||
|
},
|
||||||
|
"madrid": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.196523,
|
||||||
|
"emos_mean_crps": 1.197589,
|
||||||
|
"legacy_mean_mae": 1.380909,
|
||||||
|
"emos_mean_mae": 1.383717,
|
||||||
|
"legacy_bucket_hit_rate": 0.545455,
|
||||||
|
"emos_bucket_hit_rate": 0.636364
|
||||||
|
},
|
||||||
|
"manila": {
|
||||||
|
"samples": 5,
|
||||||
|
"legacy_mean_crps": 1.9342,
|
||||||
|
"emos_mean_crps": 1.510621,
|
||||||
|
"legacy_mean_mae": 2.408,
|
||||||
|
"emos_mean_mae": 1.914957,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"mexico city": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.560208,
|
||||||
|
"emos_mean_crps": 0.506071,
|
||||||
|
"legacy_mean_mae": 0.713,
|
||||||
|
"emos_mean_mae": 0.653865,
|
||||||
|
"legacy_bucket_hit_rate": 0.55,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"miami": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 3.359106,
|
||||||
|
"emos_mean_crps": 3.561458,
|
||||||
|
"legacy_mean_mae": 3.660455,
|
||||||
|
"emos_mean_mae": 3.936442,
|
||||||
|
"legacy_bucket_hit_rate": 0.454545,
|
||||||
|
"emos_bucket_hit_rate": 0.227273
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 1.184521,
|
||||||
|
"emos_mean_crps": 1.055058,
|
||||||
|
"legacy_mean_mae": 1.284348,
|
||||||
|
"emos_mean_mae": 1.220263,
|
||||||
|
"legacy_bucket_hit_rate": 0.304348,
|
||||||
|
"emos_bucket_hit_rate": 0.434783
|
||||||
|
},
|
||||||
|
"moscow": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.617727,
|
||||||
|
"emos_mean_crps": 0.578817,
|
||||||
|
"legacy_mean_mae": 0.6375,
|
||||||
|
"emos_mean_mae": 0.576256,
|
||||||
|
"legacy_bucket_hit_rate": 0.75,
|
||||||
|
"emos_bucket_hit_rate": 0.75
|
||||||
|
},
|
||||||
|
"munich": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.101444,
|
||||||
|
"emos_mean_crps": 1.049123,
|
||||||
|
"legacy_mean_mae": 1.298182,
|
||||||
|
"emos_mean_mae": 1.285139,
|
||||||
|
"legacy_bucket_hit_rate": 0.227273,
|
||||||
|
"emos_bucket_hit_rate": 0.227273
|
||||||
|
},
|
||||||
|
"new york": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 3.428596,
|
||||||
|
"emos_mean_crps": 3.466282,
|
||||||
|
"legacy_mean_mae": 3.988571,
|
||||||
|
"emos_mean_mae": 4.038895,
|
||||||
|
"legacy_bucket_hit_rate": 0.238095,
|
||||||
|
"emos_bucket_hit_rate": 0.238095
|
||||||
|
},
|
||||||
|
"panama city": {
|
||||||
|
"samples": 17,
|
||||||
|
"legacy_mean_crps": 0.347679,
|
||||||
|
"emos_mean_crps": 0.287754,
|
||||||
|
"legacy_mean_mae": 0.476471,
|
||||||
|
"emos_mean_mae": 0.391782,
|
||||||
|
"legacy_bucket_hit_rate": 0.588235,
|
||||||
|
"emos_bucket_hit_rate": 0.823529
|
||||||
|
},
|
||||||
|
"paris": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.718617,
|
||||||
|
"emos_mean_crps": 0.691394,
|
||||||
|
"legacy_mean_mae": 0.680455,
|
||||||
|
"emos_mean_mae": 0.696494,
|
||||||
|
"legacy_bucket_hit_rate": 0.772727,
|
||||||
|
"emos_bucket_hit_rate": 0.772727
|
||||||
|
},
|
||||||
|
"san francisco": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 2.623636,
|
||||||
|
"emos_mean_crps": 2.475182,
|
||||||
|
"legacy_mean_mae": 2.9075,
|
||||||
|
"emos_mean_mae": 2.837902,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.25
|
||||||
|
},
|
||||||
|
"sao paulo": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.930626,
|
||||||
|
"emos_mean_crps": 0.931492,
|
||||||
|
"legacy_mean_mae": 1.16,
|
||||||
|
"emos_mean_mae": 1.123038,
|
||||||
|
"legacy_bucket_hit_rate": 0.590909,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"seattle": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 1.378395,
|
||||||
|
"emos_mean_crps": 1.333721,
|
||||||
|
"legacy_mean_mae": 1.601905,
|
||||||
|
"emos_mean_mae": 1.565253,
|
||||||
|
"legacy_bucket_hit_rate": 0.428571,
|
||||||
|
"emos_bucket_hit_rate": 0.380952
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.449956,
|
||||||
|
"emos_mean_crps": 1.264612,
|
||||||
|
"legacy_mean_mae": 1.817727,
|
||||||
|
"emos_mean_mae": 1.604882,
|
||||||
|
"legacy_bucket_hit_rate": 0.409091,
|
||||||
|
"emos_bucket_hit_rate": 0.454545
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 1.237937,
|
||||||
|
"emos_mean_crps": 1.196583,
|
||||||
|
"legacy_mean_mae": 1.458261,
|
||||||
|
"emos_mean_mae": 1.430445,
|
||||||
|
"legacy_bucket_hit_rate": 0.565217,
|
||||||
|
"emos_bucket_hit_rate": 0.608696
|
||||||
|
},
|
||||||
|
"shenzhen": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 0.481109,
|
||||||
|
"emos_mean_crps": 0.444093,
|
||||||
|
"legacy_mean_mae": 0.608095,
|
||||||
|
"emos_mean_mae": 0.581253,
|
||||||
|
"legacy_bucket_hit_rate": 0.619048,
|
||||||
|
"emos_bucket_hit_rate": 0.666667
|
||||||
|
},
|
||||||
|
"singapore": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.852942,
|
||||||
|
"emos_mean_crps": 0.758454,
|
||||||
|
"legacy_mean_mae": 1.020909,
|
||||||
|
"emos_mean_mae": 0.915982,
|
||||||
|
"legacy_bucket_hit_rate": 0.409091,
|
||||||
|
"emos_bucket_hit_rate": 0.454545
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 0.801052,
|
||||||
|
"emos_mean_crps": 0.721468,
|
||||||
|
"legacy_mean_mae": 0.85087,
|
||||||
|
"emos_mean_mae": 0.814252,
|
||||||
|
"legacy_bucket_hit_rate": 0.478261,
|
||||||
|
"emos_bucket_hit_rate": 0.391304
|
||||||
|
},
|
||||||
|
"tel aviv": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.770763,
|
||||||
|
"emos_mean_crps": 0.672956,
|
||||||
|
"legacy_mean_mae": 0.904091,
|
||||||
|
"emos_mean_mae": 0.843671,
|
||||||
|
"legacy_bucket_hit_rate": 0.454545,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.651385,
|
||||||
|
"emos_mean_crps": 0.641684,
|
||||||
|
"legacy_mean_mae": 0.798182,
|
||||||
|
"emos_mean_mae": 0.787542,
|
||||||
|
"legacy_bucket_hit_rate": 0.545455,
|
||||||
|
"emos_bucket_hit_rate": 0.590909
|
||||||
|
},
|
||||||
|
"toronto": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 2.733044,
|
||||||
|
"emos_mean_crps": 2.714624,
|
||||||
|
"legacy_mean_mae": 2.981818,
|
||||||
|
"emos_mean_mae": 2.969098,
|
||||||
|
"legacy_bucket_hit_rate": 0.318182,
|
||||||
|
"emos_bucket_hit_rate": 0.409091
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 0.668776,
|
||||||
|
"emos_mean_crps": 0.665164,
|
||||||
|
"legacy_mean_mae": 0.796087,
|
||||||
|
"emos_mean_mae": 0.796958,
|
||||||
|
"legacy_bucket_hit_rate": 0.652174,
|
||||||
|
"emos_bucket_hit_rate": 0.608696
|
||||||
|
},
|
||||||
|
"wellington": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.731346,
|
||||||
|
"emos_mean_crps": 0.726977,
|
||||||
|
"legacy_mean_mae": 0.895,
|
||||||
|
"emos_mean_mae": 0.892558,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"wuhan": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.925443,
|
||||||
|
"emos_mean_crps": 0.897806,
|
||||||
|
"legacy_mean_mae": 1.0375,
|
||||||
|
"emos_mean_mae": 1.003133,
|
||||||
|
"legacy_bucket_hit_rate": 0.65,
|
||||||
|
"emos_bucket_hit_rate": 0.65
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"version": "emos-auto-20260421122743",
|
||||||
|
"generated_at": "2026-04-21T12:28:08.021388+00:00",
|
||||||
|
"candidate_dir": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743",
|
||||||
|
"candidate_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json",
|
||||||
|
"evaluation_path": "E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\evaluation_report.json",
|
||||||
|
"target_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.json",
|
||||||
|
"promote_requested": true,
|
||||||
|
"promoted": true,
|
||||||
|
"backup_path": "E:\\web\\PolyWeather\\artifacts\\probability_calibration\\default.backup-20260421122808.json",
|
||||||
|
"decision": {
|
||||||
|
"decision": "promote",
|
||||||
|
"ready_for_promotion": true,
|
||||||
|
"blocking_reasons": [],
|
||||||
|
"thresholds": {
|
||||||
|
"min_samples": 50,
|
||||||
|
"max_delta_crps": 0.0,
|
||||||
|
"max_delta_mae": 0.05,
|
||||||
|
"min_delta_bucket_hit_rate": -0.05
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 978,
|
||||||
|
"delta_crps": -0.05721,
|
||||||
|
"delta_mae": -0.034568,
|
||||||
|
"delta_bucket_hit_rate": -0.00409
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fit": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/fit_probability_calibration.py",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json",
|
||||||
|
"--version",
|
||||||
|
"emos-auto-20260421122743",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 0,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
},
|
||||||
|
"evaluate": {
|
||||||
|
"command": [
|
||||||
|
"C:\\Users\\Yang\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
|
||||||
|
"scripts/evaluate_probability_calibration.py",
|
||||||
|
"--calibration-file",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json",
|
||||||
|
"--output",
|
||||||
|
"E:\\web\\PolyWeather\\artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\evaluation_report.json",
|
||||||
|
"--verbose",
|
||||||
|
"--snapshot-limit",
|
||||||
|
"50000"
|
||||||
|
],
|
||||||
|
"returncode": 0,
|
||||||
|
"stdout": "",
|
||||||
|
"stderr": ""
|
||||||
|
},
|
||||||
|
"tests": null
|
||||||
|
}
|
||||||
+361
@@ -0,0 +1,361 @@
|
|||||||
|
{
|
||||||
|
"version": "emos-auto-20260421122743",
|
||||||
|
"trained_at": "2026-04-21T12:28:05.031165+00:00",
|
||||||
|
"global": {
|
||||||
|
"mu": {
|
||||||
|
"intercept": 0.34330438,
|
||||||
|
"raw_mu_coef": 0.48749629,
|
||||||
|
"deb_coef": 0.45733479,
|
||||||
|
"ens_median_coef": 0.05955297,
|
||||||
|
"max_so_far_gap_coef": -0.104935
|
||||||
|
},
|
||||||
|
"sigma": {
|
||||||
|
"intercept": -0.62765582,
|
||||||
|
"raw_sigma_coef": 0.38492261,
|
||||||
|
"spread_coef": 0.29095921,
|
||||||
|
"peak_flag_coef": 0.33966327,
|
||||||
|
"max_so_far_gap_coef": 0.08357376
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sigma_constraints": {
|
||||||
|
"min_ratio": 0.85,
|
||||||
|
"max_ratio": 1.35,
|
||||||
|
"absolute_min": 0.25,
|
||||||
|
"absolute_max": 3.0
|
||||||
|
},
|
||||||
|
"selection_guardrails": {
|
||||||
|
"max_mae_increase": 0.02,
|
||||||
|
"max_bucket_hit_drop": 0.01,
|
||||||
|
"max_bucket_brier_increase": 0.05
|
||||||
|
},
|
||||||
|
"blending": {
|
||||||
|
"alpha_mu": 0.25,
|
||||||
|
"alpha_sigma": 1.0
|
||||||
|
},
|
||||||
|
"cities": {
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.438949,
|
||||||
|
"sigma_scale": 0.553793,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"buenos aires": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -1.044971,
|
||||||
|
"sigma_scale": 1.389753,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"ankara": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.067406,
|
||||||
|
"sigma_scale": 1.270298,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"london": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.010833,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"paris": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.21677,
|
||||||
|
"sigma_scale": 1.095669,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"new york": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 1.072189,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"lagos": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": -0.092732,
|
||||||
|
"sigma_scale": 1.558646,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"madrid": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.627862,
|
||||||
|
"sigma_scale": 1.761239,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"toronto": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.424101,
|
||||||
|
"sigma_scale": 1.326675,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"wellington": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.347796,
|
||||||
|
"sigma_scale": 0.893459,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"los angeles": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.659983,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"san francisco": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.941818,
|
||||||
|
"sigma_scale": 1.979403,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"aurora": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 2.040009,
|
||||||
|
"sigma_scale": 0.982492,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"austin": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.990023,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"houston": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.188787,
|
||||||
|
"sigma_scale": 1.819594,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chicago": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 2.285098,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"dallas": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 0.258095,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"atlanta": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -2.093105,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"seattle": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": -0.982188,
|
||||||
|
"sigma_scale": 1.695172,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"sao paulo": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.786242,
|
||||||
|
"sigma_scale": 1.427037,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"munich": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.096559,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": -0.045038,
|
||||||
|
"sigma_scale": 1.626331,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": -0.50853,
|
||||||
|
"sigma_scale": 1.239146,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"helsinki": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": 0.442247,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"amsterdam": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": 0.129889,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"panama city": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": -0.040792,
|
||||||
|
"sigma_scale": 1.393259,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"cape town": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": 0.507293,
|
||||||
|
"sigma_scale": 1.420004,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"miami": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -2.736316,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"manila": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": 1.772229,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"singapore": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.289639,
|
||||||
|
"sigma_scale": 1.124006,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.332129,
|
||||||
|
"sigma_scale": 0.729483,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 1.6533,
|
||||||
|
"sigma_scale": 0.82648,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.343239,
|
||||||
|
"sigma_scale": 1.886868,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"mexico city": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.087122,
|
||||||
|
"sigma_scale": 1.108884,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.348022,
|
||||||
|
"sigma_scale": 0.810527,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"beijing": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.288176,
|
||||||
|
"sigma_scale": 0.952972,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"shenzhen": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": -0.006114,
|
||||||
|
"sigma_scale": 0.728494,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"wuhan": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.771154,
|
||||||
|
"sigma_scale": 1.30329,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chengdu": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.445906,
|
||||||
|
"sigma_scale": 0.796989,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chongqing": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.021301,
|
||||||
|
"sigma_scale": 1.106566,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 24,
|
||||||
|
"mu_bias": 0.37527,
|
||||||
|
"sigma_scale": 0.517756,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.600671,
|
||||||
|
"sigma_scale": 0.5,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"guangzhou": {
|
||||||
|
"samples": 6,
|
||||||
|
"mu_bias": 0.7082,
|
||||||
|
"sigma_scale": 1.975103,
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
"lau fau shan": {
|
||||||
|
"samples": 19,
|
||||||
|
"mu_bias": 0.41371,
|
||||||
|
"sigma_scale": 0.656578,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"kuala lumpur": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.499197,
|
||||||
|
"sigma_scale": 1.361171,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"jakarta": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.293537,
|
||||||
|
"sigma_scale": 0.751498,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"lucknow": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -1.593437,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"karachi": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": -0.035595,
|
||||||
|
"sigma_scale": 0.588612,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"jeddah": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": 0.516879,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"moscow": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.609602,
|
||||||
|
"sigma_scale": 0.783723,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"tel aviv": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.436837,
|
||||||
|
"sigma_scale": 1.46524,
|
||||||
|
"confidence": 1.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 978,
|
||||||
|
"mean_crps": 1.330733,
|
||||||
|
"legacy_mean_crps": 1.376936,
|
||||||
|
"legacy_mean_mae": 1.589438,
|
||||||
|
"legacy_bucket_hit_rate": 0.43865,
|
||||||
|
"legacy_bucket_brier": 0.824571,
|
||||||
|
"selected_mean_crps": 1.311763,
|
||||||
|
"selected_mean_mae": 1.553658,
|
||||||
|
"selected_bucket_hit_rate": 0.432515,
|
||||||
|
"selected_bucket_brier": 0.789817,
|
||||||
|
"selected_score": 2.910718,
|
||||||
|
"legacy_score": 2.996333,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"settlement_history_city_count": 30,
|
||||||
|
"legacy_archive_samples": 54
|
||||||
|
},
|
||||||
|
"source": "artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json"
|
||||||
|
}
|
||||||
+482
@@ -0,0 +1,482 @@
|
|||||||
|
{
|
||||||
|
"summary": {
|
||||||
|
"sample_count": 978,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"legacy": {
|
||||||
|
"mean_crps": 1.376936,
|
||||||
|
"mean_mae": 1.589438,
|
||||||
|
"bucket_hit_rate": 0.43865
|
||||||
|
},
|
||||||
|
"emos": {
|
||||||
|
"mean_crps": 1.319727,
|
||||||
|
"mean_mae": 1.554869,
|
||||||
|
"bucket_hit_rate": 0.43456
|
||||||
|
},
|
||||||
|
"delta": {
|
||||||
|
"crps": -0.05721,
|
||||||
|
"mae": -0.034568,
|
||||||
|
"bucket_hit_rate": -0.00409
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"by_city": {
|
||||||
|
"amsterdam": {
|
||||||
|
"samples": 17,
|
||||||
|
"legacy_mean_crps": 0.868937,
|
||||||
|
"emos_mean_crps": 0.847633,
|
||||||
|
"legacy_mean_mae": 0.983529,
|
||||||
|
"emos_mean_mae": 0.979456,
|
||||||
|
"legacy_bucket_hit_rate": 0.529412,
|
||||||
|
"emos_bucket_hit_rate": 0.470588
|
||||||
|
},
|
||||||
|
"ankara": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 0.610138,
|
||||||
|
"emos_mean_crps": 0.569029,
|
||||||
|
"legacy_mean_mae": 0.726087,
|
||||||
|
"emos_mean_mae": 0.731312,
|
||||||
|
"legacy_bucket_hit_rate": 0.434783,
|
||||||
|
"emos_bucket_hit_rate": 0.391304
|
||||||
|
},
|
||||||
|
"atlanta": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 4.304444,
|
||||||
|
"emos_mean_crps": 4.435438,
|
||||||
|
"legacy_mean_mae": 4.79,
|
||||||
|
"emos_mean_mae": 4.992948,
|
||||||
|
"legacy_bucket_hit_rate": 0.181818,
|
||||||
|
"emos_bucket_hit_rate": 0.090909
|
||||||
|
},
|
||||||
|
"aurora": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 3.989577,
|
||||||
|
"emos_mean_crps": 3.688746,
|
||||||
|
"legacy_mean_mae": 4.5115,
|
||||||
|
"emos_mean_mae": 4.454993,
|
||||||
|
"legacy_bucket_hit_rate": 0.1,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"austin": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 2.261424,
|
||||||
|
"emos_mean_crps": 2.109386,
|
||||||
|
"legacy_mean_mae": 2.422,
|
||||||
|
"emos_mean_mae": 2.377675,
|
||||||
|
"legacy_bucket_hit_rate": 0.45,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"beijing": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.116518,
|
||||||
|
"emos_mean_crps": 1.123144,
|
||||||
|
"legacy_mean_mae": 1.4955,
|
||||||
|
"emos_mean_mae": 1.468371,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"buenos aires": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.632274,
|
||||||
|
"emos_mean_crps": 1.657172,
|
||||||
|
"legacy_mean_mae": 1.885,
|
||||||
|
"emos_mean_mae": 1.875542,
|
||||||
|
"legacy_bucket_hit_rate": 0.454545,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 16,
|
||||||
|
"legacy_mean_crps": 1.066146,
|
||||||
|
"emos_mean_crps": 0.99263,
|
||||||
|
"legacy_mean_mae": 1.304375,
|
||||||
|
"emos_mean_mae": 1.259453,
|
||||||
|
"legacy_bucket_hit_rate": 0.375,
|
||||||
|
"emos_bucket_hit_rate": 0.375
|
||||||
|
},
|
||||||
|
"cape town": {
|
||||||
|
"samples": 10,
|
||||||
|
"legacy_mean_crps": 0.7369,
|
||||||
|
"emos_mean_crps": 0.646728,
|
||||||
|
"legacy_mean_mae": 0.882,
|
||||||
|
"emos_mean_mae": 0.809407,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"chengdu": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.009046,
|
||||||
|
"emos_mean_crps": 0.964076,
|
||||||
|
"legacy_mean_mae": 1.1835,
|
||||||
|
"emos_mean_mae": 1.155294,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"chicago": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 3.052956,
|
||||||
|
"emos_mean_crps": 2.842851,
|
||||||
|
"legacy_mean_mae": 3.398095,
|
||||||
|
"emos_mean_mae": 3.312975,
|
||||||
|
"legacy_bucket_hit_rate": 0.285714,
|
||||||
|
"emos_bucket_hit_rate": 0.095238
|
||||||
|
},
|
||||||
|
"chongqing": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.239078,
|
||||||
|
"emos_mean_crps": 1.231804,
|
||||||
|
"legacy_mean_mae": 1.4955,
|
||||||
|
"emos_mean_mae": 1.501486,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.4
|
||||||
|
},
|
||||||
|
"dallas": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 1.795116,
|
||||||
|
"emos_mean_crps": 1.700865,
|
||||||
|
"legacy_mean_mae": 1.979048,
|
||||||
|
"emos_mean_mae": 2.017151,
|
||||||
|
"legacy_bucket_hit_rate": 0.285714,
|
||||||
|
"emos_bucket_hit_rate": 0.238095
|
||||||
|
},
|
||||||
|
"guangzhou": {
|
||||||
|
"samples": 6,
|
||||||
|
"legacy_mean_crps": 1.586654,
|
||||||
|
"emos_mean_crps": 1.565936,
|
||||||
|
"legacy_mean_mae": 1.991667,
|
||||||
|
"emos_mean_mae": 1.995792,
|
||||||
|
"legacy_bucket_hit_rate": 0.166667,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"helsinki": {
|
||||||
|
"samples": 17,
|
||||||
|
"legacy_mean_crps": 0.626777,
|
||||||
|
"emos_mean_crps": 0.489382,
|
||||||
|
"legacy_mean_mae": 0.785294,
|
||||||
|
"emos_mean_mae": 0.640606,
|
||||||
|
"legacy_bucket_hit_rate": 0.470588,
|
||||||
|
"emos_bucket_hit_rate": 0.529412
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 24,
|
||||||
|
"legacy_mean_crps": 0.531004,
|
||||||
|
"emos_mean_crps": 0.473302,
|
||||||
|
"legacy_mean_mae": 0.552917,
|
||||||
|
"emos_mean_mae": 0.52881,
|
||||||
|
"legacy_bucket_hit_rate": 0.666667,
|
||||||
|
"emos_bucket_hit_rate": 0.75
|
||||||
|
},
|
||||||
|
"houston": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 1.488859,
|
||||||
|
"emos_mean_crps": 1.412564,
|
||||||
|
"legacy_mean_mae": 1.8085,
|
||||||
|
"emos_mean_mae": 1.80359,
|
||||||
|
"legacy_bucket_hit_rate": 0.25,
|
||||||
|
"emos_bucket_hit_rate": 0.2
|
||||||
|
},
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.586067,
|
||||||
|
"emos_mean_crps": 0.546494,
|
||||||
|
"legacy_mean_mae": 0.6225,
|
||||||
|
"emos_mean_mae": 0.557255,
|
||||||
|
"legacy_bucket_hit_rate": 0.7,
|
||||||
|
"emos_bucket_hit_rate": 0.7
|
||||||
|
},
|
||||||
|
"jakarta": {
|
||||||
|
"samples": 16,
|
||||||
|
"legacy_mean_crps": 0.620583,
|
||||||
|
"emos_mean_crps": 0.553084,
|
||||||
|
"legacy_mean_mae": 0.875625,
|
||||||
|
"emos_mean_mae": 0.793719,
|
||||||
|
"legacy_bucket_hit_rate": 0.4375,
|
||||||
|
"emos_bucket_hit_rate": 0.4375
|
||||||
|
},
|
||||||
|
"jeddah": {
|
||||||
|
"samples": 10,
|
||||||
|
"legacy_mean_crps": 1.822658,
|
||||||
|
"emos_mean_crps": 1.674198,
|
||||||
|
"legacy_mean_mae": 2.277,
|
||||||
|
"emos_mean_mae": 2.192556,
|
||||||
|
"legacy_bucket_hit_rate": 0.2,
|
||||||
|
"emos_bucket_hit_rate": 0.1
|
||||||
|
},
|
||||||
|
"karachi": {
|
||||||
|
"samples": 5,
|
||||||
|
"legacy_mean_crps": 0.361328,
|
||||||
|
"emos_mean_crps": 0.326866,
|
||||||
|
"legacy_mean_mae": 0.398,
|
||||||
|
"emos_mean_mae": 0.336276,
|
||||||
|
"legacy_bucket_hit_rate": 0.8,
|
||||||
|
"emos_bucket_hit_rate": 0.8
|
||||||
|
},
|
||||||
|
"kuala lumpur": {
|
||||||
|
"samples": 16,
|
||||||
|
"legacy_mean_crps": 0.927888,
|
||||||
|
"emos_mean_crps": 0.86633,
|
||||||
|
"legacy_mean_mae": 1.146875,
|
||||||
|
"emos_mean_mae": 1.083193,
|
||||||
|
"legacy_bucket_hit_rate": 0.375,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"lagos": {
|
||||||
|
"samples": 10,
|
||||||
|
"legacy_mean_crps": 1.174893,
|
||||||
|
"emos_mean_crps": 1.204827,
|
||||||
|
"legacy_mean_mae": 1.592,
|
||||||
|
"emos_mean_mae": 1.586221,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"lau fau shan": {
|
||||||
|
"samples": 19,
|
||||||
|
"legacy_mean_crps": 0.713018,
|
||||||
|
"emos_mean_crps": 0.63244,
|
||||||
|
"legacy_mean_mae": 0.706316,
|
||||||
|
"emos_mean_mae": 0.641667,
|
||||||
|
"legacy_bucket_hit_rate": 0.578947,
|
||||||
|
"emos_bucket_hit_rate": 0.578947
|
||||||
|
},
|
||||||
|
"london": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.298133,
|
||||||
|
"emos_mean_crps": 1.267504,
|
||||||
|
"legacy_mean_mae": 1.429091,
|
||||||
|
"emos_mean_mae": 1.422989,
|
||||||
|
"legacy_bucket_hit_rate": 0.409091,
|
||||||
|
"emos_bucket_hit_rate": 0.409091
|
||||||
|
},
|
||||||
|
"los angeles": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 2.051516,
|
||||||
|
"emos_mean_crps": 2.006381,
|
||||||
|
"legacy_mean_mae": 2.4145,
|
||||||
|
"emos_mean_mae": 2.366065,
|
||||||
|
"legacy_bucket_hit_rate": 0.3,
|
||||||
|
"emos_bucket_hit_rate": 0.3
|
||||||
|
},
|
||||||
|
"lucknow": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.134917,
|
||||||
|
"emos_mean_crps": 0.890494,
|
||||||
|
"legacy_mean_mae": 1.532727,
|
||||||
|
"emos_mean_mae": 1.201547,
|
||||||
|
"legacy_bucket_hit_rate": 0.136364,
|
||||||
|
"emos_bucket_hit_rate": 0.272727
|
||||||
|
},
|
||||||
|
"madrid": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.196523,
|
||||||
|
"emos_mean_crps": 1.197589,
|
||||||
|
"legacy_mean_mae": 1.380909,
|
||||||
|
"emos_mean_mae": 1.383717,
|
||||||
|
"legacy_bucket_hit_rate": 0.545455,
|
||||||
|
"emos_bucket_hit_rate": 0.636364
|
||||||
|
},
|
||||||
|
"manila": {
|
||||||
|
"samples": 5,
|
||||||
|
"legacy_mean_crps": 1.9342,
|
||||||
|
"emos_mean_crps": 1.510621,
|
||||||
|
"legacy_mean_mae": 2.408,
|
||||||
|
"emos_mean_mae": 1.914957,
|
||||||
|
"legacy_bucket_hit_rate": 0.0,
|
||||||
|
"emos_bucket_hit_rate": 0.0
|
||||||
|
},
|
||||||
|
"mexico city": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.560208,
|
||||||
|
"emos_mean_crps": 0.506071,
|
||||||
|
"legacy_mean_mae": 0.713,
|
||||||
|
"emos_mean_mae": 0.653865,
|
||||||
|
"legacy_bucket_hit_rate": 0.55,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"miami": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 3.359106,
|
||||||
|
"emos_mean_crps": 3.561458,
|
||||||
|
"legacy_mean_mae": 3.660455,
|
||||||
|
"emos_mean_mae": 3.936442,
|
||||||
|
"legacy_bucket_hit_rate": 0.454545,
|
||||||
|
"emos_bucket_hit_rate": 0.227273
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 1.184521,
|
||||||
|
"emos_mean_crps": 1.055058,
|
||||||
|
"legacy_mean_mae": 1.284348,
|
||||||
|
"emos_mean_mae": 1.220263,
|
||||||
|
"legacy_bucket_hit_rate": 0.304348,
|
||||||
|
"emos_bucket_hit_rate": 0.434783
|
||||||
|
},
|
||||||
|
"moscow": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.617727,
|
||||||
|
"emos_mean_crps": 0.578817,
|
||||||
|
"legacy_mean_mae": 0.6375,
|
||||||
|
"emos_mean_mae": 0.576256,
|
||||||
|
"legacy_bucket_hit_rate": 0.75,
|
||||||
|
"emos_bucket_hit_rate": 0.75
|
||||||
|
},
|
||||||
|
"munich": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.101444,
|
||||||
|
"emos_mean_crps": 1.049123,
|
||||||
|
"legacy_mean_mae": 1.298182,
|
||||||
|
"emos_mean_mae": 1.285139,
|
||||||
|
"legacy_bucket_hit_rate": 0.227273,
|
||||||
|
"emos_bucket_hit_rate": 0.227273
|
||||||
|
},
|
||||||
|
"new york": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 3.428596,
|
||||||
|
"emos_mean_crps": 3.466282,
|
||||||
|
"legacy_mean_mae": 3.988571,
|
||||||
|
"emos_mean_mae": 4.038895,
|
||||||
|
"legacy_bucket_hit_rate": 0.238095,
|
||||||
|
"emos_bucket_hit_rate": 0.238095
|
||||||
|
},
|
||||||
|
"panama city": {
|
||||||
|
"samples": 17,
|
||||||
|
"legacy_mean_crps": 0.347679,
|
||||||
|
"emos_mean_crps": 0.287754,
|
||||||
|
"legacy_mean_mae": 0.476471,
|
||||||
|
"emos_mean_mae": 0.391782,
|
||||||
|
"legacy_bucket_hit_rate": 0.588235,
|
||||||
|
"emos_bucket_hit_rate": 0.823529
|
||||||
|
},
|
||||||
|
"paris": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.718617,
|
||||||
|
"emos_mean_crps": 0.691394,
|
||||||
|
"legacy_mean_mae": 0.680455,
|
||||||
|
"emos_mean_mae": 0.696494,
|
||||||
|
"legacy_bucket_hit_rate": 0.772727,
|
||||||
|
"emos_bucket_hit_rate": 0.772727
|
||||||
|
},
|
||||||
|
"san francisco": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 2.623636,
|
||||||
|
"emos_mean_crps": 2.475182,
|
||||||
|
"legacy_mean_mae": 2.9075,
|
||||||
|
"emos_mean_mae": 2.837902,
|
||||||
|
"legacy_bucket_hit_rate": 0.4,
|
||||||
|
"emos_bucket_hit_rate": 0.25
|
||||||
|
},
|
||||||
|
"sao paulo": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.930626,
|
||||||
|
"emos_mean_crps": 0.931492,
|
||||||
|
"legacy_mean_mae": 1.16,
|
||||||
|
"emos_mean_mae": 1.123038,
|
||||||
|
"legacy_bucket_hit_rate": 0.590909,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"seattle": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 1.378395,
|
||||||
|
"emos_mean_crps": 1.333721,
|
||||||
|
"legacy_mean_mae": 1.601905,
|
||||||
|
"emos_mean_mae": 1.565253,
|
||||||
|
"legacy_bucket_hit_rate": 0.428571,
|
||||||
|
"emos_bucket_hit_rate": 0.380952
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 1.449956,
|
||||||
|
"emos_mean_crps": 1.264612,
|
||||||
|
"legacy_mean_mae": 1.817727,
|
||||||
|
"emos_mean_mae": 1.604882,
|
||||||
|
"legacy_bucket_hit_rate": 0.409091,
|
||||||
|
"emos_bucket_hit_rate": 0.454545
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 1.237937,
|
||||||
|
"emos_mean_crps": 1.196583,
|
||||||
|
"legacy_mean_mae": 1.458261,
|
||||||
|
"emos_mean_mae": 1.430445,
|
||||||
|
"legacy_bucket_hit_rate": 0.565217,
|
||||||
|
"emos_bucket_hit_rate": 0.608696
|
||||||
|
},
|
||||||
|
"shenzhen": {
|
||||||
|
"samples": 21,
|
||||||
|
"legacy_mean_crps": 0.481109,
|
||||||
|
"emos_mean_crps": 0.444093,
|
||||||
|
"legacy_mean_mae": 0.608095,
|
||||||
|
"emos_mean_mae": 0.581253,
|
||||||
|
"legacy_bucket_hit_rate": 0.619048,
|
||||||
|
"emos_bucket_hit_rate": 0.666667
|
||||||
|
},
|
||||||
|
"singapore": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.852942,
|
||||||
|
"emos_mean_crps": 0.758454,
|
||||||
|
"legacy_mean_mae": 1.020909,
|
||||||
|
"emos_mean_mae": 0.915982,
|
||||||
|
"legacy_bucket_hit_rate": 0.409091,
|
||||||
|
"emos_bucket_hit_rate": 0.454545
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 0.801052,
|
||||||
|
"emos_mean_crps": 0.721468,
|
||||||
|
"legacy_mean_mae": 0.85087,
|
||||||
|
"emos_mean_mae": 0.814252,
|
||||||
|
"legacy_bucket_hit_rate": 0.478261,
|
||||||
|
"emos_bucket_hit_rate": 0.391304
|
||||||
|
},
|
||||||
|
"tel aviv": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.770763,
|
||||||
|
"emos_mean_crps": 0.672956,
|
||||||
|
"legacy_mean_mae": 0.904091,
|
||||||
|
"emos_mean_mae": 0.843671,
|
||||||
|
"legacy_bucket_hit_rate": 0.454545,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.651385,
|
||||||
|
"emos_mean_crps": 0.641684,
|
||||||
|
"legacy_mean_mae": 0.798182,
|
||||||
|
"emos_mean_mae": 0.787542,
|
||||||
|
"legacy_bucket_hit_rate": 0.545455,
|
||||||
|
"emos_bucket_hit_rate": 0.590909
|
||||||
|
},
|
||||||
|
"toronto": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 2.733044,
|
||||||
|
"emos_mean_crps": 2.714624,
|
||||||
|
"legacy_mean_mae": 2.981818,
|
||||||
|
"emos_mean_mae": 2.969098,
|
||||||
|
"legacy_bucket_hit_rate": 0.318182,
|
||||||
|
"emos_bucket_hit_rate": 0.409091
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 23,
|
||||||
|
"legacy_mean_crps": 0.668776,
|
||||||
|
"emos_mean_crps": 0.665164,
|
||||||
|
"legacy_mean_mae": 0.796087,
|
||||||
|
"emos_mean_mae": 0.796958,
|
||||||
|
"legacy_bucket_hit_rate": 0.652174,
|
||||||
|
"emos_bucket_hit_rate": 0.608696
|
||||||
|
},
|
||||||
|
"wellington": {
|
||||||
|
"samples": 22,
|
||||||
|
"legacy_mean_crps": 0.731346,
|
||||||
|
"emos_mean_crps": 0.726977,
|
||||||
|
"legacy_mean_mae": 0.895,
|
||||||
|
"emos_mean_mae": 0.892558,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"emos_bucket_hit_rate": 0.5
|
||||||
|
},
|
||||||
|
"wuhan": {
|
||||||
|
"samples": 20,
|
||||||
|
"legacy_mean_crps": 0.925443,
|
||||||
|
"emos_mean_crps": 0.897806,
|
||||||
|
"legacy_mean_mae": 1.0375,
|
||||||
|
"emos_mean_mae": 1.003133,
|
||||||
|
"legacy_bucket_hit_rate": 0.65,
|
||||||
|
"emos_bucket_hit_rate": 0.65
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"version": "emos-20260418192717",
|
||||||
|
"trained_at": "2026-04-18T19:27:17.348931+00:00",
|
||||||
|
"global": {
|
||||||
|
"mu": {
|
||||||
|
"intercept": 2.60074353,
|
||||||
|
"raw_mu_coef": 1.97765258,
|
||||||
|
"deb_coef": -1.37457626,
|
||||||
|
"ens_median_coef": 0.10693472,
|
||||||
|
"max_so_far_gap_coef": -0.58256593
|
||||||
|
},
|
||||||
|
"sigma": {
|
||||||
|
"intercept": 0.6373609,
|
||||||
|
"raw_sigma_coef": -1.41537225,
|
||||||
|
"spread_coef": 2.12997577,
|
||||||
|
"peak_flag_coef": -0.08633203,
|
||||||
|
"max_so_far_gap_coef": -0.00716383
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sigma_constraints": {
|
||||||
|
"min_ratio": 0.85,
|
||||||
|
"max_ratio": 1.35,
|
||||||
|
"absolute_min": 0.25,
|
||||||
|
"absolute_max": 3.0
|
||||||
|
},
|
||||||
|
"selection_guardrails": {
|
||||||
|
"max_mae_increase": 0.02,
|
||||||
|
"max_bucket_hit_drop": 0.01,
|
||||||
|
"max_bucket_brier_increase": 0.05
|
||||||
|
},
|
||||||
|
"blending": {
|
||||||
|
"alpha_mu": 0.05,
|
||||||
|
"alpha_sigma": 0.7
|
||||||
|
},
|
||||||
|
"cities": {
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": 2.101101,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"ankara": {
|
||||||
|
"samples": 6,
|
||||||
|
"mu_bias": -0.523145,
|
||||||
|
"sigma_scale": 1.139849,
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
"istanbul": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -0.285183,
|
||||||
|
"sigma_scale": 0.550171,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 7,
|
||||||
|
"mu_bias": 3.234676,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.875
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": 4.731246,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"busan": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": 0.177772,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"seoul": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -3.070325,
|
||||||
|
"sigma_scale": 1.462196,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -4.249866,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"shanghai": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": 1.080039,
|
||||||
|
"sigma_scale": 1.638119,
|
||||||
|
"confidence": 0.375
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 3,
|
||||||
|
"mu_bias": -1.68611,
|
||||||
|
"sigma_scale": 1.38114,
|
||||||
|
"confidence": 0.375
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"sample_count": 74,
|
||||||
|
"mean_crps": 3.181501,
|
||||||
|
"legacy_mean_crps": 3.474108,
|
||||||
|
"legacy_mean_mae": 3.679324,
|
||||||
|
"legacy_bucket_hit_rate": 0.5,
|
||||||
|
"legacy_bucket_brier": 0.855395,
|
||||||
|
"selected_mean_crps": 3.322469,
|
||||||
|
"selected_mean_mae": 3.618254,
|
||||||
|
"selected_bucket_hit_rate": 0.5,
|
||||||
|
"selected_bucket_brier": 0.863048,
|
||||||
|
"selected_score": 5.08158,
|
||||||
|
"legacy_score": 5.233586,
|
||||||
|
"filled_actual_from_history": 0,
|
||||||
|
"settlement_history_city_count": 30,
|
||||||
|
"legacy_archive_samples": 54
|
||||||
|
},
|
||||||
|
"source": "artifacts\\probability_calibration\\default.json"
|
||||||
|
}
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"version": "emos-20260418192717",
|
"version": "emos-auto-20260421122743",
|
||||||
"trained_at": "2026-04-18T19:27:17.348931+00:00",
|
"trained_at": "2026-04-21T12:28:05.031165+00:00",
|
||||||
"global": {
|
"global": {
|
||||||
"mu": {
|
"mu": {
|
||||||
"intercept": 2.60074353,
|
"intercept": 0.34330438,
|
||||||
"raw_mu_coef": 1.97765258,
|
"raw_mu_coef": 0.48749629,
|
||||||
"deb_coef": -1.37457626,
|
"deb_coef": 0.45733479,
|
||||||
"ens_median_coef": 0.10693472,
|
"ens_median_coef": 0.05955297,
|
||||||
"max_so_far_gap_coef": -0.58256593
|
"max_so_far_gap_coef": -0.104935
|
||||||
},
|
},
|
||||||
"sigma": {
|
"sigma": {
|
||||||
"intercept": 0.6373609,
|
"intercept": -0.62765582,
|
||||||
"raw_sigma_coef": -1.41537225,
|
"raw_sigma_coef": 0.38492261,
|
||||||
"spread_coef": 2.12997577,
|
"spread_coef": 0.29095921,
|
||||||
"peak_flag_coef": -0.08633203,
|
"peak_flag_coef": 0.33966327,
|
||||||
"max_so_far_gap_coef": -0.00716383
|
"max_so_far_gap_coef": 0.08357376
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sigma_constraints": {
|
"sigma_constraints": {
|
||||||
@@ -29,87 +29,333 @@
|
|||||||
"max_bucket_brier_increase": 0.05
|
"max_bucket_brier_increase": 0.05
|
||||||
},
|
},
|
||||||
"blending": {
|
"blending": {
|
||||||
"alpha_mu": 0.05,
|
"alpha_mu": 0.25,
|
||||||
"alpha_sigma": 0.7
|
"alpha_sigma": 1.0
|
||||||
},
|
},
|
||||||
"cities": {
|
"cities": {
|
||||||
"tokyo": {
|
"istanbul": {
|
||||||
"samples": 5,
|
"samples": 20,
|
||||||
"mu_bias": 2.101101,
|
"mu_bias": -0.438949,
|
||||||
"sigma_scale": 2.0,
|
"sigma_scale": 0.553793,
|
||||||
"confidence": 0.625
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"buenos aires": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -1.044971,
|
||||||
|
"sigma_scale": 1.389753,
|
||||||
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"ankara": {
|
"ankara": {
|
||||||
"samples": 6,
|
"samples": 23,
|
||||||
"mu_bias": -0.523145,
|
"mu_bias": 0.067406,
|
||||||
"sigma_scale": 1.139849,
|
"sigma_scale": 1.270298,
|
||||||
"confidence": 0.75
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"istanbul": {
|
"london": {
|
||||||
"samples": 3,
|
"samples": 22,
|
||||||
"mu_bias": -0.285183,
|
"mu_bias": -0.010833,
|
||||||
"sigma_scale": 0.550171,
|
|
||||||
"confidence": 0.375
|
|
||||||
},
|
|
||||||
"hong kong": {
|
|
||||||
"samples": 7,
|
|
||||||
"mu_bias": 3.234676,
|
|
||||||
"sigma_scale": 2.0,
|
"sigma_scale": 2.0,
|
||||||
"confidence": 0.875
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"taipei": {
|
"paris": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.21677,
|
||||||
|
"sigma_scale": 1.095669,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"new york": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 1.072189,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"lagos": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": -0.092732,
|
||||||
|
"sigma_scale": 1.558646,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"madrid": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.627862,
|
||||||
|
"sigma_scale": 1.761239,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"toronto": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.424101,
|
||||||
|
"sigma_scale": 1.326675,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"wellington": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.347796,
|
||||||
|
"sigma_scale": 0.893459,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"los angeles": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.659983,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"san francisco": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.941818,
|
||||||
|
"sigma_scale": 1.979403,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"aurora": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 2.040009,
|
||||||
|
"sigma_scale": 0.982492,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"austin": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.990023,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"houston": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.188787,
|
||||||
|
"sigma_scale": 1.819594,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chicago": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 2.285098,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"dallas": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": 0.258095,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"atlanta": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -2.093105,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"seattle": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": -0.982188,
|
||||||
|
"sigma_scale": 1.695172,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"sao paulo": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.786242,
|
||||||
|
"sigma_scale": 1.427037,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"munich": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.096559,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"milan": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": -0.045038,
|
||||||
|
"sigma_scale": 1.626331,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"warsaw": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": -0.50853,
|
||||||
|
"sigma_scale": 1.239146,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"helsinki": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": 0.442247,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"amsterdam": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": 0.129889,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"panama city": {
|
||||||
|
"samples": 17,
|
||||||
|
"mu_bias": -0.040792,
|
||||||
|
"sigma_scale": 1.393259,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"cape town": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": 0.507293,
|
||||||
|
"sigma_scale": 1.420004,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"miami": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -2.736316,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"manila": {
|
||||||
"samples": 5,
|
"samples": 5,
|
||||||
"mu_bias": 4.731246,
|
"mu_bias": 1.772229,
|
||||||
"sigma_scale": 2.0,
|
"sigma_scale": 2.0,
|
||||||
"confidence": 0.625
|
"confidence": 0.625
|
||||||
},
|
},
|
||||||
"busan": {
|
"singapore": {
|
||||||
"samples": 3,
|
"samples": 22,
|
||||||
"mu_bias": 0.177772,
|
"mu_bias": 0.289639,
|
||||||
"sigma_scale": 2.0,
|
"sigma_scale": 1.124006,
|
||||||
"confidence": 0.375
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"tokyo": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -0.332129,
|
||||||
|
"sigma_scale": 0.729483,
|
||||||
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"seoul": {
|
"seoul": {
|
||||||
"samples": 3,
|
"samples": 22,
|
||||||
"mu_bias": -3.070325,
|
"mu_bias": 1.6533,
|
||||||
"sigma_scale": 1.462196,
|
"sigma_scale": 0.82648,
|
||||||
"confidence": 0.375
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"milan": {
|
"busan": {
|
||||||
"samples": 3,
|
"samples": 16,
|
||||||
"mu_bias": -4.249866,
|
"mu_bias": 0.343239,
|
||||||
"sigma_scale": 2.0,
|
"sigma_scale": 1.886868,
|
||||||
"confidence": 0.375
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"mexico city": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.087122,
|
||||||
|
"sigma_scale": 1.108884,
|
||||||
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"shanghai": {
|
"shanghai": {
|
||||||
"samples": 3,
|
"samples": 23,
|
||||||
"mu_bias": 1.080039,
|
"mu_bias": 0.348022,
|
||||||
"sigma_scale": 1.638119,
|
"sigma_scale": 0.810527,
|
||||||
"confidence": 0.375
|
"confidence": 1.0
|
||||||
},
|
},
|
||||||
"warsaw": {
|
"beijing": {
|
||||||
"samples": 3,
|
"samples": 20,
|
||||||
"mu_bias": -1.68611,
|
"mu_bias": -0.288176,
|
||||||
"sigma_scale": 1.38114,
|
"sigma_scale": 0.952972,
|
||||||
"confidence": 0.375
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"shenzhen": {
|
||||||
|
"samples": 21,
|
||||||
|
"mu_bias": -0.006114,
|
||||||
|
"sigma_scale": 0.728494,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"wuhan": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.771154,
|
||||||
|
"sigma_scale": 1.30329,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chengdu": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": 0.445906,
|
||||||
|
"sigma_scale": 0.796989,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"chongqing": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.021301,
|
||||||
|
"sigma_scale": 1.106566,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"hong kong": {
|
||||||
|
"samples": 24,
|
||||||
|
"mu_bias": 0.37527,
|
||||||
|
"sigma_scale": 0.517756,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"taipei": {
|
||||||
|
"samples": 23,
|
||||||
|
"mu_bias": 0.600671,
|
||||||
|
"sigma_scale": 0.5,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"guangzhou": {
|
||||||
|
"samples": 6,
|
||||||
|
"mu_bias": 0.7082,
|
||||||
|
"sigma_scale": 1.975103,
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
"lau fau shan": {
|
||||||
|
"samples": 19,
|
||||||
|
"mu_bias": 0.41371,
|
||||||
|
"sigma_scale": 0.656578,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"kuala lumpur": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.499197,
|
||||||
|
"sigma_scale": 1.361171,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"jakarta": {
|
||||||
|
"samples": 16,
|
||||||
|
"mu_bias": 0.293537,
|
||||||
|
"sigma_scale": 0.751498,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"lucknow": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": -1.593437,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"karachi": {
|
||||||
|
"samples": 5,
|
||||||
|
"mu_bias": -0.035595,
|
||||||
|
"sigma_scale": 0.588612,
|
||||||
|
"confidence": 0.625
|
||||||
|
},
|
||||||
|
"jeddah": {
|
||||||
|
"samples": 10,
|
||||||
|
"mu_bias": 0.516879,
|
||||||
|
"sigma_scale": 2.0,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"moscow": {
|
||||||
|
"samples": 20,
|
||||||
|
"mu_bias": -0.609602,
|
||||||
|
"sigma_scale": 0.783723,
|
||||||
|
"confidence": 1.0
|
||||||
|
},
|
||||||
|
"tel aviv": {
|
||||||
|
"samples": 22,
|
||||||
|
"mu_bias": 0.436837,
|
||||||
|
"sigma_scale": 1.46524,
|
||||||
|
"confidence": 1.0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"sample_count": 74,
|
"sample_count": 978,
|
||||||
"mean_crps": 3.181501,
|
"mean_crps": 1.330733,
|
||||||
"legacy_mean_crps": 3.474108,
|
"legacy_mean_crps": 1.376936,
|
||||||
"legacy_mean_mae": 3.679324,
|
"legacy_mean_mae": 1.589438,
|
||||||
"legacy_bucket_hit_rate": 0.5,
|
"legacy_bucket_hit_rate": 0.43865,
|
||||||
"legacy_bucket_brier": 0.855395,
|
"legacy_bucket_brier": 0.824571,
|
||||||
"selected_mean_crps": 3.322469,
|
"selected_mean_crps": 1.311763,
|
||||||
"selected_mean_mae": 3.618254,
|
"selected_mean_mae": 1.553658,
|
||||||
"selected_bucket_hit_rate": 0.5,
|
"selected_bucket_hit_rate": 0.432515,
|
||||||
"selected_bucket_brier": 0.863048,
|
"selected_bucket_brier": 0.789817,
|
||||||
"selected_score": 5.08158,
|
"selected_score": 2.910718,
|
||||||
"legacy_score": 5.233586,
|
"legacy_score": 2.996333,
|
||||||
"filled_actual_from_history": 0,
|
"filled_actual_from_history": 0,
|
||||||
"settlement_history_city_count": 30,
|
"settlement_history_city_count": 30,
|
||||||
"legacy_archive_samples": 54
|
"legacy_archive_samples": 54
|
||||||
},
|
},
|
||||||
"source": "artifacts\\probability_calibration\\default.json"
|
"source": "artifacts\\local_runtime\\probability_calibration\\candidates\\emos-auto-20260421122743\\default.json"
|
||||||
}
|
}
|
||||||
@@ -1075,6 +1075,72 @@
|
|||||||
border: 1px solid rgba(251, 113, 133, 0.26);
|
border: 1px solid rgba(251, 113, 133, 0.26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-card) {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid rgba(34, 211, 238, 0.16);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(8, 20, 32, 0.52);
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-head) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-head span) {
|
||||||
|
color: var(--cyan);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-head strong) {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-grid) {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-grid > div) {
|
||||||
|
display: grid;
|
||||||
|
gap: 3px;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.12);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(15, 23, 42, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-grid span),
|
||||||
|
.root :global(.prob-price-grid em),
|
||||||
|
.root :global(.prob-price-card p) {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 11px;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-grid strong) {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-card p) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.root :global(.prob-model-hint) {
|
.root :global(.prob-model-hint) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -2466,6 +2532,15 @@
|
|||||||
.root :global(.marker-name) {
|
.root :global(.marker-name) {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-grid) {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(.prob-price-head) {
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── History Modal ── */
|
/* ── History Modal ── */
|
||||||
|
|||||||
@@ -278,6 +278,29 @@ function normalizeMarketProbability(value?: number | null) {
|
|||||||
return Math.max(0, Math.min(1, numeric));
|
return Math.max(0, Math.min(1, numeric));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSignedProbability(value?: number | null) {
|
||||||
|
if (value == null) return null;
|
||||||
|
const numeric = Number(value);
|
||||||
|
if (!Number.isFinite(numeric)) return null;
|
||||||
|
if (Math.abs(numeric) > 1) return numeric / 100;
|
||||||
|
return numeric;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSignedPercent(value?: number | null, digits = 1) {
|
||||||
|
const normalized = normalizeSignedProbability(value);
|
||||||
|
if (normalized == null) return "--";
|
||||||
|
const percent = normalized * 100;
|
||||||
|
const sign = percent > 0 ? "+" : "";
|
||||||
|
return `${sign}${percent.toFixed(digits)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatKellyFraction(value?: number | null) {
|
||||||
|
const normalized = normalizeSignedProbability(value);
|
||||||
|
if (normalized == null) return "--";
|
||||||
|
if (normalized <= 0) return "0%";
|
||||||
|
return `${(normalized * 100).toFixed(1)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
function getMarketTopBuckets(scan?: MarketScan | null) {
|
function getMarketTopBuckets(scan?: MarketScan | null) {
|
||||||
const buckets = Array.isArray(scan?.top_buckets) ? scan.top_buckets : [];
|
const buckets = Array.isArray(scan?.top_buckets) ? scan.top_buckets : [];
|
||||||
if (!buckets.length) return [];
|
if (!buckets.length) return [];
|
||||||
@@ -657,6 +680,38 @@ export function ProbabilityDistribution({
|
|||||||
const topProbabilityLabel = topProbability
|
const topProbabilityLabel = topProbability
|
||||||
? topProbability.label || `${topProbability.value}${detail.temp_symbol}`
|
? topProbability.label || `${topProbability.value}${detail.temp_symbol}`
|
||||||
: null;
|
: null;
|
||||||
|
const priceAnalysis = marketScan?.price_analysis;
|
||||||
|
const yesPriceView = priceAnalysis?.yes;
|
||||||
|
const noPriceView = priceAnalysis?.no;
|
||||||
|
const preferredPriceView =
|
||||||
|
priceAnalysis?.best_side === "no" ? noPriceView : yesPriceView;
|
||||||
|
const preferredSideLabel =
|
||||||
|
priceAnalysis?.best_side === "no"
|
||||||
|
? locale === "en-US"
|
||||||
|
? "NO"
|
||||||
|
: "NO"
|
||||||
|
: locale === "en-US"
|
||||||
|
? "YES"
|
||||||
|
: "YES";
|
||||||
|
const hasPriceAnalysis =
|
||||||
|
Boolean(priceAnalysis?.available) &&
|
||||||
|
(yesPriceView?.ask != null || noPriceView?.ask != null);
|
||||||
|
const lockEdge = normalizeSignedProbability(priceAnalysis?.lock?.edge);
|
||||||
|
const lockAvailable = Boolean(priceAnalysis?.lock?.available && lockEdge != null);
|
||||||
|
const quoteSource =
|
||||||
|
marketScan?.yes_token?.quote_source ||
|
||||||
|
marketScan?.no_token?.quote_source ||
|
||||||
|
null;
|
||||||
|
const quoteAgeMs =
|
||||||
|
marketScan?.yes_token?.quote_age_ms ?? marketScan?.no_token?.quote_age_ms;
|
||||||
|
const quoteSourceLabel =
|
||||||
|
quoteSource === "polymarket_ws"
|
||||||
|
? locale === "en-US"
|
||||||
|
? `WS live${quoteAgeMs != null ? ` · ${Math.max(0, Math.round(Number(quoteAgeMs) / 1000))}s` : ""}`
|
||||||
|
: `WS 实时${quoteAgeMs != null ? ` · ${Math.max(0, Math.round(Number(quoteAgeMs) / 1000))}秒` : ""}`
|
||||||
|
: locale === "en-US"
|
||||||
|
? "CLOB fallback"
|
||||||
|
: "CLOB 兜底";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="prob-section">
|
<section className="prob-section">
|
||||||
@@ -702,6 +757,63 @@ export function ProbabilityDistribution({
|
|||||||
: `市场仅作参考:该温度桶 ${marketYesText}`}
|
: `市场仅作参考:该温度桶 ${marketYesText}`}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{hasPriceAnalysis && (
|
||||||
|
<div className="prob-price-card">
|
||||||
|
<div className="prob-price-head">
|
||||||
|
<span>
|
||||||
|
{locale === "en-US" ? "Price reference" : "价格参考"}
|
||||||
|
</span>
|
||||||
|
<strong>
|
||||||
|
{preferredPriceView?.edge != null
|
||||||
|
? locale === "en-US"
|
||||||
|
? `${preferredSideLabel} edge ${formatSignedPercent(preferredPriceView.edge)}`
|
||||||
|
: `${preferredSideLabel} 边际 ${formatSignedPercent(preferredPriceView.edge)}`
|
||||||
|
: locale === "en-US"
|
||||||
|
? "Waiting for executable quote"
|
||||||
|
: "等待可执行报价"}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div className="prob-price-grid">
|
||||||
|
<div>
|
||||||
|
<span>YES ask</span>
|
||||||
|
<strong>{toPriceCents(yesPriceView?.ask) || "--"}</strong>
|
||||||
|
<em>{formatSignedPercent(yesPriceView?.edge)}</em>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>NO ask</span>
|
||||||
|
<strong>{toPriceCents(noPriceView?.ask) || "--"}</strong>
|
||||||
|
<em>{formatSignedPercent(noPriceView?.edge)}</em>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{locale === "en-US" ? "1/4 Kelly" : "1/4 Kelly"}</span>
|
||||||
|
<strong>{formatKellyFraction(preferredPriceView?.quarter_kelly)}</strong>
|
||||||
|
<em>{locale === "en-US" ? "cap required" : "需限额"}</em>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{locale === "en-US" ? "Lock" : "锁价"}</span>
|
||||||
|
<strong>
|
||||||
|
{lockAvailable
|
||||||
|
? formatSignedPercent(lockEdge)
|
||||||
|
: locale === "en-US"
|
||||||
|
? "None"
|
||||||
|
: "无"}
|
||||||
|
</strong>
|
||||||
|
<em>
|
||||||
|
{priceAnalysis?.lock?.ask_sum != null
|
||||||
|
? locale === "en-US"
|
||||||
|
? `sum ${toPriceCents(priceAnalysis.lock.ask_sum)}`
|
||||||
|
: `合计 ${toPriceCents(priceAnalysis.lock.ask_sum)}`
|
||||||
|
: "--"}
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
{locale === "en-US"
|
||||||
|
? `Read-only sizing reference from executable quotes; it does not place orders. Source: ${quoteSourceLabel}.`
|
||||||
|
: `基于可执行盘口的只读仓位参考;系统不会下单。来源:${quoteSourceLabel}。`}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{modelVoteHint && (
|
{modelVoteHint && (
|
||||||
<div className="prob-model-hint">
|
<div className="prob-model-hint">
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -289,6 +289,8 @@ export interface MarketToken {
|
|||||||
sell_price?: number | null;
|
sell_price?: number | null;
|
||||||
midpoint?: number | null;
|
midpoint?: number | null;
|
||||||
last_trade_price?: number | null;
|
last_trade_price?: number | null;
|
||||||
|
quote_source?: string | null;
|
||||||
|
quote_age_ms?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarketPrimary {
|
export interface MarketPrimary {
|
||||||
@@ -314,11 +316,42 @@ export interface MarketTopBucket {
|
|||||||
yes_sell?: number | null;
|
yes_sell?: number | null;
|
||||||
no_buy?: number | null;
|
no_buy?: number | null;
|
||||||
no_sell?: number | null;
|
no_sell?: number | null;
|
||||||
|
quote_source?: string | null;
|
||||||
|
quote_age_ms?: number | null;
|
||||||
slug?: string | null;
|
slug?: string | null;
|
||||||
question?: string | null;
|
question?: string | null;
|
||||||
is_primary?: boolean;
|
is_primary?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MarketPriceSide {
|
||||||
|
side?: "yes" | "no" | string | null;
|
||||||
|
model_probability?: number | null;
|
||||||
|
ask?: number | null;
|
||||||
|
bid?: number | null;
|
||||||
|
edge?: number | null;
|
||||||
|
edge_percent?: number | null;
|
||||||
|
kelly_fraction?: number | null;
|
||||||
|
quarter_kelly?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketPriceAnalysis {
|
||||||
|
available?: boolean;
|
||||||
|
source?: string | null;
|
||||||
|
model_probability?: number | null;
|
||||||
|
yes?: MarketPriceSide | null;
|
||||||
|
no?: MarketPriceSide | null;
|
||||||
|
best_side?: "yes" | "no" | string | null;
|
||||||
|
lock?: {
|
||||||
|
available?: boolean;
|
||||||
|
ask_sum?: number | null;
|
||||||
|
edge?: number | null;
|
||||||
|
} | null;
|
||||||
|
sell_side?: {
|
||||||
|
bid_sum?: number | null;
|
||||||
|
edge?: number | null;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MarketScan {
|
export interface MarketScan {
|
||||||
available?: boolean;
|
available?: boolean;
|
||||||
reason?: string | null;
|
reason?: string | null;
|
||||||
@@ -343,6 +376,7 @@ export interface MarketScan {
|
|||||||
last_trade_price?: number | null;
|
last_trade_price?: number | null;
|
||||||
liquidity?: number | null;
|
liquidity?: number | null;
|
||||||
volume?: number | null;
|
volume?: number | null;
|
||||||
|
price_analysis?: MarketPriceAnalysis | null;
|
||||||
sparkline?: number[];
|
sparkline?: number[];
|
||||||
top_buckets?: MarketTopBucket[] | null;
|
top_buckets?: MarketTopBucket[] | null;
|
||||||
recent_trades?: unknown[];
|
recent_trades?: unknown[];
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ lightgbm
|
|||||||
web3
|
web3
|
||||||
fastapi
|
fastapi
|
||||||
uvicorn
|
uvicorn
|
||||||
|
websockets
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import httpx
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from src.data_collection.city_registry import ALIASES, CITY_REGISTRY
|
from src.data_collection.city_registry import ALIASES, CITY_REGISTRY
|
||||||
|
from src.data_collection.polymarket_ws_cache import PolymarketWsQuoteCache
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from py_clob_client.client import ClobClient # type: ignore
|
from py_clob_client.client import ClobClient # type: ignore
|
||||||
@@ -173,6 +174,16 @@ def _extract_price(value: Any) -> Optional[float]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _clamp_probability(value: Optional[float]) -> Optional[float]:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
if value < 0.0:
|
||||||
|
return 0.0
|
||||||
|
if value > 1.0:
|
||||||
|
return 1.0
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def _extract_iso_date(value: Any) -> Optional[str]:
|
def _extract_iso_date(value: Any) -> Optional[str]:
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
@@ -394,6 +405,7 @@ class PolymarketReadOnlyLayer:
|
|||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
self._clob_client: Any = None
|
self._clob_client: Any = None
|
||||||
self._clob_unavailable_reason: Optional[str] = None
|
self._clob_unavailable_reason: Optional[str] = None
|
||||||
|
self._ws_quote_cache = PolymarketWsQuoteCache.from_env()
|
||||||
|
|
||||||
def build_market_scan(
|
def build_market_scan(
|
||||||
self,
|
self,
|
||||||
@@ -430,6 +442,7 @@ class PolymarketReadOnlyLayer:
|
|||||||
"last_trade_price": None,
|
"last_trade_price": None,
|
||||||
"liquidity": None,
|
"liquidity": None,
|
||||||
"volume": None,
|
"volume": None,
|
||||||
|
"price_analysis": None,
|
||||||
"sparkline": fallback_sparkline or [],
|
"sparkline": fallback_sparkline or [],
|
||||||
"top_buckets": [],
|
"top_buckets": [],
|
||||||
"recent_trades": [],
|
"recent_trades": [],
|
||||||
@@ -570,6 +583,8 @@ class PolymarketReadOnlyLayer:
|
|||||||
"sell_price": _extract_price(yes_prices.get("sell")),
|
"sell_price": _extract_price(yes_prices.get("sell")),
|
||||||
"midpoint": _extract_price(yes_prices.get("midpoint")),
|
"midpoint": _extract_price(yes_prices.get("midpoint")),
|
||||||
"last_trade_price": _extract_price(yes_prices.get("last_trade_price")),
|
"last_trade_price": _extract_price(yes_prices.get("last_trade_price")),
|
||||||
|
"quote_source": yes_prices.get("quote_source"),
|
||||||
|
"quote_age_ms": _safe_int(yes_prices.get("quote_age_ms"), 0),
|
||||||
"book": yes_prices.get("book"),
|
"book": yes_prices.get("book"),
|
||||||
}
|
}
|
||||||
no_payload = {
|
no_payload = {
|
||||||
@@ -580,8 +595,17 @@ class PolymarketReadOnlyLayer:
|
|||||||
"sell_price": _extract_price(no_prices.get("sell")),
|
"sell_price": _extract_price(no_prices.get("sell")),
|
||||||
"midpoint": _extract_price(no_prices.get("midpoint")),
|
"midpoint": _extract_price(no_prices.get("midpoint")),
|
||||||
"last_trade_price": _extract_price(no_prices.get("last_trade_price")),
|
"last_trade_price": _extract_price(no_prices.get("last_trade_price")),
|
||||||
|
"quote_source": no_prices.get("quote_source"),
|
||||||
|
"quote_age_ms": _safe_int(no_prices.get("quote_age_ms"), 0),
|
||||||
"book": no_prices.get("book"),
|
"book": no_prices.get("book"),
|
||||||
}
|
}
|
||||||
|
price_analysis = self._build_price_analysis(
|
||||||
|
model_probability=model_probability,
|
||||||
|
yes_buy=_extract_price(yes_payload.get("buy_price")),
|
||||||
|
yes_sell=_extract_price(yes_payload.get("sell_price")),
|
||||||
|
no_buy=_extract_price(no_payload.get("buy_price")),
|
||||||
|
no_sell=_extract_price(no_payload.get("sell_price")),
|
||||||
|
)
|
||||||
|
|
||||||
sparkline_values: List[float] = []
|
sparkline_values: List[float] = []
|
||||||
for candidate in (
|
for candidate in (
|
||||||
@@ -617,12 +641,15 @@ class PolymarketReadOnlyLayer:
|
|||||||
"last_trade_price": last_trade_price,
|
"last_trade_price": last_trade_price,
|
||||||
"liquidity": liquidity,
|
"liquidity": liquidity,
|
||||||
"volume": volume,
|
"volume": volume,
|
||||||
|
"price_analysis": price_analysis,
|
||||||
"sparkline": sparkline_values,
|
"sparkline": sparkline_values,
|
||||||
"top_buckets": top_buckets,
|
"top_buckets": top_buckets,
|
||||||
"all_buckets": all_buckets,
|
"all_buckets": all_buckets,
|
||||||
"websocket": {
|
"websocket": {
|
||||||
"market_url": market_url,
|
"enabled": self._ws_quote_cache.enabled,
|
||||||
"asset_ids": [
|
"status": self._ws_quote_cache.status(),
|
||||||
|
"market_url": market_url,
|
||||||
|
"asset_ids": [
|
||||||
token
|
token
|
||||||
for token in [
|
for token in [
|
||||||
yes_payload.get("token_id"),
|
yes_payload.get("token_id"),
|
||||||
@@ -636,6 +663,112 @@ class PolymarketReadOnlyLayer:
|
|||||||
)
|
)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
|
def _build_price_analysis(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
model_probability: Optional[float],
|
||||||
|
yes_buy: Optional[float],
|
||||||
|
yes_sell: Optional[float],
|
||||||
|
no_buy: Optional[float],
|
||||||
|
no_sell: Optional[float],
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""Build read-only market price diagnostics.
|
||||||
|
|
||||||
|
Polymarket CLOB naming is from the user's perspective:
|
||||||
|
BUY is the executable ask to buy that outcome, SELL is the executable bid.
|
||||||
|
Kelly here is a sizing reference only; no order execution is performed.
|
||||||
|
"""
|
||||||
|
p_yes = _clamp_probability(_safe_float(model_probability))
|
||||||
|
p_no = _clamp_probability(1.0 - p_yes if p_yes is not None else None)
|
||||||
|
yes_ask = _clamp_probability(_safe_float(yes_buy))
|
||||||
|
no_ask = _clamp_probability(_safe_float(no_buy))
|
||||||
|
yes_bid = _clamp_probability(_safe_float(yes_sell))
|
||||||
|
no_bid = _clamp_probability(_safe_float(no_sell))
|
||||||
|
|
||||||
|
yes = self._build_side_price_analysis("yes", p_yes, yes_ask, yes_bid)
|
||||||
|
no = self._build_side_price_analysis("no", p_no, no_ask, no_bid)
|
||||||
|
|
||||||
|
ask_sum = None
|
||||||
|
lock_edge = None
|
||||||
|
lock_available = False
|
||||||
|
if yes_ask is not None and no_ask is not None:
|
||||||
|
ask_sum = yes_ask + no_ask
|
||||||
|
lock_edge = 1.0 - ask_sum
|
||||||
|
lock_available = lock_edge > 0
|
||||||
|
|
||||||
|
bid_sum = None
|
||||||
|
sell_side_edge = None
|
||||||
|
if yes_bid is not None and no_bid is not None:
|
||||||
|
bid_sum = yes_bid + no_bid
|
||||||
|
sell_side_edge = bid_sum - 1.0
|
||||||
|
|
||||||
|
best_side = None
|
||||||
|
side_rows = [
|
||||||
|
row
|
||||||
|
for row in [yes, no]
|
||||||
|
if isinstance(row.get("edge"), (int, float))
|
||||||
|
and isinstance(row.get("kelly_fraction"), (int, float))
|
||||||
|
and row.get("kelly_fraction") > 0
|
||||||
|
]
|
||||||
|
if side_rows:
|
||||||
|
best_side = max(
|
||||||
|
side_rows,
|
||||||
|
key=lambda row: (
|
||||||
|
float(row.get("edge") or 0.0),
|
||||||
|
float(row.get("kelly_fraction") or 0.0),
|
||||||
|
),
|
||||||
|
).get("side")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"available": any(
|
||||||
|
value is not None
|
||||||
|
for value in (yes_ask, no_ask, yes_bid, no_bid, p_yes)
|
||||||
|
),
|
||||||
|
"source": "polymarket_clob_orderbook",
|
||||||
|
"model_probability": p_yes,
|
||||||
|
"yes": yes,
|
||||||
|
"no": no,
|
||||||
|
"best_side": best_side,
|
||||||
|
"lock": {
|
||||||
|
"available": lock_available,
|
||||||
|
"ask_sum": ask_sum,
|
||||||
|
"edge": lock_edge,
|
||||||
|
},
|
||||||
|
"sell_side": {
|
||||||
|
"bid_sum": bid_sum,
|
||||||
|
"edge": sell_side_edge,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _build_side_price_analysis(
|
||||||
|
self,
|
||||||
|
side: str,
|
||||||
|
probability: Optional[float],
|
||||||
|
ask: Optional[float],
|
||||||
|
bid: Optional[float],
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
edge = None
|
||||||
|
kelly_fraction = None
|
||||||
|
if probability is not None and ask is not None:
|
||||||
|
edge = probability - ask
|
||||||
|
if 0.0 < ask < 1.0:
|
||||||
|
kelly_fraction = edge / (1.0 - ask)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"side": side,
|
||||||
|
"model_probability": probability,
|
||||||
|
"ask": ask,
|
||||||
|
"bid": bid,
|
||||||
|
"edge": edge,
|
||||||
|
"edge_percent": edge * 100.0 if edge is not None else None,
|
||||||
|
"kelly_fraction": kelly_fraction,
|
||||||
|
"quarter_kelly": (
|
||||||
|
max(0.0, kelly_fraction) / 4.0
|
||||||
|
if kelly_fraction is not None
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
def _market_trade_state(self, market: Dict[str, Any]) -> Dict[str, Any]:
|
def _market_trade_state(self, market: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
active = _safe_bool(market.get("active"))
|
active = _safe_bool(market.get("active"))
|
||||||
closed_raw = _safe_bool(market.get("closed"))
|
closed_raw = _safe_bool(market.get("closed"))
|
||||||
@@ -1193,6 +1326,11 @@ class PolymarketReadOnlyLayer:
|
|||||||
if not token_id:
|
if not token_id:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
self._ws_quote_cache.subscribe([token_id])
|
||||||
|
ws_data = self._ws_quote_cache.get_market_data(token_id)
|
||||||
|
if ws_data is not None:
|
||||||
|
return ws_data
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
with self._lock:
|
with self._lock:
|
||||||
cached = self._price_cache.get(token_id)
|
cached = self._price_cache.get(token_id)
|
||||||
@@ -1473,6 +1611,8 @@ class PolymarketReadOnlyLayer:
|
|||||||
"yes_sell": yes_sell,
|
"yes_sell": yes_sell,
|
||||||
"no_buy": no_buy,
|
"no_buy": no_buy,
|
||||||
"no_sell": no_sell,
|
"no_sell": no_sell,
|
||||||
|
"quote_source": yes_prices.get("quote_source"),
|
||||||
|
"quote_age_ms": _safe_int(yes_prices.get("quote_age_ms"), 0),
|
||||||
"slug": market_slug or None,
|
"slug": market_slug or None,
|
||||||
"question": market.get("question") or market.get("title"),
|
"question": market.get("question") or market.get("title"),
|
||||||
"is_primary": bool(
|
"is_primary": bool(
|
||||||
|
|||||||
@@ -0,0 +1,404 @@
|
|||||||
|
"""
|
||||||
|
Read-only Polymarket market WebSocket quote cache.
|
||||||
|
|
||||||
|
The cache subscribes to public market-channel asset ids and stores executable
|
||||||
|
best bid / ask updates. It is deliberately optional: callers should keep REST
|
||||||
|
or CLOB polling as a fallback when the WebSocket client is unavailable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
from typing import Any, Dict, Iterable, Optional, Set
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_float(value: Any) -> Optional[float]:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
if isinstance(value, str):
|
||||||
|
value = value.strip()
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
|
numeric = float(value)
|
||||||
|
if math.isnan(numeric) or math.isinf(numeric):
|
||||||
|
return None
|
||||||
|
return numeric
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _env_bool(name: str, default: bool = False) -> bool:
|
||||||
|
raw = os.getenv(name)
|
||||||
|
if raw is None:
|
||||||
|
return default
|
||||||
|
return raw.strip().lower() in {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
|
|
||||||
|
class PolymarketWsQuoteCache:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
enabled: bool = False,
|
||||||
|
endpoint: Optional[str] = None,
|
||||||
|
quote_ttl_sec: int = 8,
|
||||||
|
max_assets: int = 256,
|
||||||
|
reconnect_delay_sec: float = 3.0,
|
||||||
|
) -> None:
|
||||||
|
self.enabled = enabled
|
||||||
|
self.endpoint = (
|
||||||
|
endpoint
|
||||||
|
or os.getenv(
|
||||||
|
"POLYMARKET_WS_MARKET_URL",
|
||||||
|
"wss://ws-subscriptions-clob.polymarket.com/ws/market",
|
||||||
|
)
|
||||||
|
or ""
|
||||||
|
).strip()
|
||||||
|
self.quote_ttl_sec = max(1, int(quote_ttl_sec or 8))
|
||||||
|
self.max_assets = max(1, int(max_assets or 256))
|
||||||
|
self.reconnect_delay_sec = max(0.5, float(reconnect_delay_sec or 3.0))
|
||||||
|
|
||||||
|
self._desired_assets: Set[str] = set()
|
||||||
|
self._quotes: Dict[str, Dict[str, Any]] = {}
|
||||||
|
self._lock = threading.Lock()
|
||||||
|
self._thread: Optional[threading.Thread] = None
|
||||||
|
self._stop_event = threading.Event()
|
||||||
|
self._started = False
|
||||||
|
self._last_error: Optional[str] = None
|
||||||
|
self._last_connected_at: Optional[float] = None
|
||||||
|
self._last_message_at: Optional[float] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_env(cls) -> "PolymarketWsQuoteCache":
|
||||||
|
return cls(
|
||||||
|
enabled=_env_bool("POLYMARKET_WS_PRICE_ENABLED", False),
|
||||||
|
endpoint=os.getenv("POLYMARKET_WS_MARKET_URL"),
|
||||||
|
quote_ttl_sec=int(os.getenv("POLYMARKET_WS_QUOTE_TTL_SEC", "8")),
|
||||||
|
max_assets=int(os.getenv("POLYMARKET_WS_MAX_ASSETS", "256")),
|
||||||
|
reconnect_delay_sec=float(
|
||||||
|
os.getenv("POLYMARKET_WS_RECONNECT_DELAY_SEC", "3")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def start(self) -> None:
|
||||||
|
if not self.enabled or not self.endpoint:
|
||||||
|
return
|
||||||
|
with self._lock:
|
||||||
|
if self._started:
|
||||||
|
return
|
||||||
|
self._started = True
|
||||||
|
self._thread = threading.Thread(
|
||||||
|
target=self._thread_main,
|
||||||
|
name="polymarket-ws-quotes",
|
||||||
|
daemon=True,
|
||||||
|
)
|
||||||
|
self._thread.start()
|
||||||
|
|
||||||
|
def stop(self) -> None:
|
||||||
|
self._stop_event.set()
|
||||||
|
|
||||||
|
def subscribe(self, asset_ids: Iterable[Any]) -> None:
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
normalized = []
|
||||||
|
for asset_id in asset_ids:
|
||||||
|
text = str(asset_id or "").strip()
|
||||||
|
if text:
|
||||||
|
normalized.append(text)
|
||||||
|
if not normalized:
|
||||||
|
return
|
||||||
|
|
||||||
|
with self._lock:
|
||||||
|
remaining = self.max_assets - len(self._desired_assets)
|
||||||
|
for asset_id in normalized:
|
||||||
|
if asset_id in self._desired_assets:
|
||||||
|
continue
|
||||||
|
if remaining <= 0:
|
||||||
|
break
|
||||||
|
self._desired_assets.add(asset_id)
|
||||||
|
remaining -= 1
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def get_market_data(self, asset_id: Any) -> Optional[Dict[str, Any]]:
|
||||||
|
quote = self.get_quote(asset_id)
|
||||||
|
if not quote:
|
||||||
|
return None
|
||||||
|
|
||||||
|
best_bid = _safe_float(quote.get("best_bid"))
|
||||||
|
best_ask = _safe_float(quote.get("best_ask"))
|
||||||
|
if best_bid is None and best_ask is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
midpoint = None
|
||||||
|
if best_bid is not None and best_ask is not None:
|
||||||
|
midpoint = (best_bid + best_ask) / 2.0
|
||||||
|
|
||||||
|
age_ms = int((time.time() - float(quote.get("t") or time.time())) * 1000)
|
||||||
|
return {
|
||||||
|
"buy": best_ask,
|
||||||
|
"sell": best_bid,
|
||||||
|
"midpoint": midpoint,
|
||||||
|
"last_trade_price": _safe_float(quote.get("last_trade_price")),
|
||||||
|
"book": {
|
||||||
|
"best_bid": best_bid,
|
||||||
|
"best_ask": best_ask,
|
||||||
|
"bid_levels": [[best_bid, 0.0]] if best_bid is not None else [],
|
||||||
|
"ask_levels": [[best_ask, 0.0]] if best_ask is not None else [],
|
||||||
|
},
|
||||||
|
"book_liquidity": None,
|
||||||
|
"quote_source": "polymarket_ws",
|
||||||
|
"quote_age_ms": age_ms,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_quote(self, asset_id: Any) -> Optional[Dict[str, Any]]:
|
||||||
|
text = str(asset_id or "").strip()
|
||||||
|
if not text:
|
||||||
|
return None
|
||||||
|
now = time.time()
|
||||||
|
with self._lock:
|
||||||
|
quote = self._quotes.get(text)
|
||||||
|
if not quote:
|
||||||
|
return None
|
||||||
|
if now - float(quote.get("t") or 0.0) > self.quote_ttl_sec:
|
||||||
|
return None
|
||||||
|
return dict(quote)
|
||||||
|
|
||||||
|
def status(self) -> Dict[str, Any]:
|
||||||
|
with self._lock:
|
||||||
|
return {
|
||||||
|
"enabled": self.enabled,
|
||||||
|
"started": self._started,
|
||||||
|
"endpoint": self.endpoint,
|
||||||
|
"asset_count": len(self._desired_assets),
|
||||||
|
"quote_count": len(self._quotes),
|
||||||
|
"last_error": self._last_error,
|
||||||
|
"last_connected_at": self._last_connected_at,
|
||||||
|
"last_message_at": self._last_message_at,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _thread_main(self) -> None:
|
||||||
|
try:
|
||||||
|
asyncio.run(self._run_forever())
|
||||||
|
except Exception as exc: # pragma: no cover - defensive thread guard
|
||||||
|
with self._lock:
|
||||||
|
self._last_error = str(exc)
|
||||||
|
logger.warning(f"Polymarket WS quote cache stopped: {exc}")
|
||||||
|
|
||||||
|
async def _run_forever(self) -> None:
|
||||||
|
try:
|
||||||
|
import websockets # type: ignore
|
||||||
|
except Exception as exc:
|
||||||
|
with self._lock:
|
||||||
|
self._last_error = f"websockets import failed: {exc}"
|
||||||
|
logger.warning(self._last_error)
|
||||||
|
return
|
||||||
|
|
||||||
|
while not self._stop_event.is_set():
|
||||||
|
try:
|
||||||
|
async with websockets.connect(
|
||||||
|
self.endpoint,
|
||||||
|
ping_interval=None,
|
||||||
|
close_timeout=2,
|
||||||
|
) as ws:
|
||||||
|
with self._lock:
|
||||||
|
self._last_connected_at = time.time()
|
||||||
|
self._last_error = None
|
||||||
|
subscribed: Set[str] = set()
|
||||||
|
last_ping = 0.0
|
||||||
|
|
||||||
|
while not self._stop_event.is_set():
|
||||||
|
desired = self._snapshot_assets()
|
||||||
|
missing = desired - subscribed
|
||||||
|
if missing:
|
||||||
|
await self._send_subscription(
|
||||||
|
ws,
|
||||||
|
missing,
|
||||||
|
initial=not subscribed,
|
||||||
|
)
|
||||||
|
subscribed.update(missing)
|
||||||
|
|
||||||
|
now = time.time()
|
||||||
|
if now - last_ping >= 10:
|
||||||
|
await ws.send(json.dumps({}))
|
||||||
|
last_ping = now
|
||||||
|
|
||||||
|
try:
|
||||||
|
raw = await asyncio.wait_for(ws.recv(), timeout=1.0)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
continue
|
||||||
|
self._handle_message(raw)
|
||||||
|
except Exception as exc:
|
||||||
|
with self._lock:
|
||||||
|
self._last_error = str(exc)
|
||||||
|
logger.warning(f"Polymarket WS reconnecting after error: {exc}")
|
||||||
|
await asyncio.sleep(self.reconnect_delay_sec)
|
||||||
|
|
||||||
|
def _snapshot_assets(self) -> Set[str]:
|
||||||
|
with self._lock:
|
||||||
|
return set(self._desired_assets)
|
||||||
|
|
||||||
|
async def _send_subscription(
|
||||||
|
self,
|
||||||
|
ws: Any,
|
||||||
|
asset_ids: Iterable[str],
|
||||||
|
*,
|
||||||
|
initial: bool,
|
||||||
|
) -> None:
|
||||||
|
batch = [asset_id for asset_id in asset_ids if asset_id]
|
||||||
|
if not batch:
|
||||||
|
return
|
||||||
|
payload = {
|
||||||
|
"assets_ids": batch,
|
||||||
|
"custom_feature_enabled": True,
|
||||||
|
}
|
||||||
|
if initial:
|
||||||
|
payload["type"] = "market"
|
||||||
|
else:
|
||||||
|
payload["operation"] = "subscribe"
|
||||||
|
await ws.send(json.dumps(payload))
|
||||||
|
|
||||||
|
def _handle_message(self, raw: Any) -> None:
|
||||||
|
if raw in (None, "", "PONG"):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
payload = json.loads(raw) if isinstance(raw, str) else raw
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
|
||||||
|
if isinstance(payload, list):
|
||||||
|
for item in payload:
|
||||||
|
self._handle_event(item)
|
||||||
|
return
|
||||||
|
self._handle_event(payload)
|
||||||
|
|
||||||
|
def _handle_event(self, event: Any) -> None:
|
||||||
|
if not isinstance(event, dict):
|
||||||
|
return
|
||||||
|
if "event_type" in event:
|
||||||
|
event_type = str(event.get("event_type") or "").strip().lower()
|
||||||
|
else:
|
||||||
|
event_type = str(event.get("type") or "").strip().lower()
|
||||||
|
|
||||||
|
if event_type in {
|
||||||
|
"best_bid_ask",
|
||||||
|
"price_change",
|
||||||
|
"book",
|
||||||
|
"last_trade_price",
|
||||||
|
}:
|
||||||
|
self._handle_quote_event(event_type, event)
|
||||||
|
|
||||||
|
def _handle_quote_event(self, event_type: str, event: Dict[str, Any]) -> None:
|
||||||
|
candidates = (
|
||||||
|
event.get("price_changes")
|
||||||
|
or event.get("changes")
|
||||||
|
or event.get("assets")
|
||||||
|
or event.get("data")
|
||||||
|
)
|
||||||
|
if isinstance(candidates, list):
|
||||||
|
for item in candidates:
|
||||||
|
if isinstance(item, dict):
|
||||||
|
self._upsert_quote(event_type, item, parent=event)
|
||||||
|
return
|
||||||
|
self._upsert_quote(event_type, event, parent=event)
|
||||||
|
|
||||||
|
def _upsert_quote(
|
||||||
|
self,
|
||||||
|
event_type: str,
|
||||||
|
item: Dict[str, Any],
|
||||||
|
*,
|
||||||
|
parent: Dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
asset_id = str(
|
||||||
|
item.get("asset_id")
|
||||||
|
or item.get("assetId")
|
||||||
|
or item.get("token_id")
|
||||||
|
or item.get("tokenId")
|
||||||
|
or parent.get("asset_id")
|
||||||
|
or parent.get("assetId")
|
||||||
|
or ""
|
||||||
|
).strip()
|
||||||
|
if not asset_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
best_bid = (
|
||||||
|
_safe_float(item.get("best_bid"))
|
||||||
|
or _safe_float(item.get("bid"))
|
||||||
|
or _safe_float(item.get("bestBid"))
|
||||||
|
)
|
||||||
|
best_ask = (
|
||||||
|
_safe_float(item.get("best_ask"))
|
||||||
|
or _safe_float(item.get("ask"))
|
||||||
|
or _safe_float(item.get("bestAsk"))
|
||||||
|
)
|
||||||
|
if event_type == "book":
|
||||||
|
parsed_bid, parsed_ask = self._extract_book_top(item)
|
||||||
|
best_bid = best_bid if best_bid is not None else parsed_bid
|
||||||
|
best_ask = best_ask if best_ask is not None else parsed_ask
|
||||||
|
price = _safe_float(item.get("price"))
|
||||||
|
side = str(item.get("side") or "").strip().upper()
|
||||||
|
if event_type == "price_change" and price is not None:
|
||||||
|
if side == "BUY":
|
||||||
|
best_ask = price
|
||||||
|
elif side == "SELL":
|
||||||
|
best_bid = price
|
||||||
|
|
||||||
|
last_trade = (
|
||||||
|
_safe_float(item.get("last_trade_price"))
|
||||||
|
or _safe_float(item.get("lastTradePrice"))
|
||||||
|
or (price if event_type == "last_trade_price" else None)
|
||||||
|
)
|
||||||
|
|
||||||
|
now = time.time()
|
||||||
|
with self._lock:
|
||||||
|
previous = dict(self._quotes.get(asset_id) or {})
|
||||||
|
if best_bid is not None:
|
||||||
|
previous["best_bid"] = best_bid
|
||||||
|
if best_ask is not None:
|
||||||
|
previous["best_ask"] = best_ask
|
||||||
|
if last_trade is not None:
|
||||||
|
previous["last_trade_price"] = last_trade
|
||||||
|
previous["asset_id"] = asset_id
|
||||||
|
previous["event_type"] = event_type
|
||||||
|
previous["t"] = now
|
||||||
|
self._quotes[asset_id] = previous
|
||||||
|
self._last_message_at = now
|
||||||
|
|
||||||
|
def _extract_book_top(
|
||||||
|
self,
|
||||||
|
payload: Dict[str, Any],
|
||||||
|
) -> tuple[Optional[float], Optional[float]]:
|
||||||
|
best_bid = None
|
||||||
|
best_ask = None
|
||||||
|
|
||||||
|
bids = payload.get("bids")
|
||||||
|
if isinstance(bids, list):
|
||||||
|
for item in bids:
|
||||||
|
price = self._extract_level_price(item)
|
||||||
|
if price is None:
|
||||||
|
continue
|
||||||
|
best_bid = price if best_bid is None else max(best_bid, price)
|
||||||
|
|
||||||
|
asks = payload.get("asks")
|
||||||
|
if isinstance(asks, list):
|
||||||
|
for item in asks:
|
||||||
|
price = self._extract_level_price(item)
|
||||||
|
if price is None:
|
||||||
|
continue
|
||||||
|
best_ask = price if best_ask is None else min(best_ask, price)
|
||||||
|
|
||||||
|
return best_bid, best_ask
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _extract_level_price(level: Any) -> Optional[float]:
|
||||||
|
if isinstance(level, dict):
|
||||||
|
return _safe_float(level.get("price"))
|
||||||
|
if isinstance(level, (list, tuple)) and level:
|
||||||
|
return _safe_float(level[0])
|
||||||
|
return None
|
||||||
@@ -61,6 +61,62 @@ def test_fetch_token_market_data_prefers_orderbook_executable_prices():
|
|||||||
assert data["last_trade_price"] == 0.49
|
assert data["last_trade_price"] == 0.49
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_token_market_data_prefers_fresh_ws_cache():
|
||||||
|
layer = PolymarketReadOnlyLayer()
|
||||||
|
|
||||||
|
class FakeWsCache:
|
||||||
|
enabled = True
|
||||||
|
|
||||||
|
def subscribe(self, asset_ids):
|
||||||
|
self.asset_ids = list(asset_ids)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_market_data(_token_id):
|
||||||
|
return {
|
||||||
|
"buy": 0.33,
|
||||||
|
"sell": 0.31,
|
||||||
|
"midpoint": 0.32,
|
||||||
|
"quote_source": "polymarket_ws",
|
||||||
|
"quote_age_ms": 80,
|
||||||
|
}
|
||||||
|
|
||||||
|
layer._ws_quote_cache = FakeWsCache()
|
||||||
|
layer._fetch_token_market_data = lambda _token_id: {"buy": 0.99}
|
||||||
|
|
||||||
|
data = layer._get_token_market_data("token-1")
|
||||||
|
|
||||||
|
assert data["buy"] == 0.33
|
||||||
|
assert data["sell"] == 0.31
|
||||||
|
assert data["quote_source"] == "polymarket_ws"
|
||||||
|
|
||||||
|
|
||||||
|
def test_price_analysis_computes_edge_kelly_and_lock():
|
||||||
|
layer = PolymarketReadOnlyLayer()
|
||||||
|
|
||||||
|
analysis = layer._build_price_analysis(
|
||||||
|
model_probability=0.62,
|
||||||
|
yes_buy=0.52,
|
||||||
|
yes_sell=0.50,
|
||||||
|
no_buy=0.45,
|
||||||
|
no_sell=0.43,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert analysis["available"] is True
|
||||||
|
assert abs(analysis["yes"]["edge"] - 0.10) < 0.000001
|
||||||
|
assert round(analysis["yes"]["kelly_fraction"], 6) == round(
|
||||||
|
(0.62 - 0.52) / (1.0 - 0.52),
|
||||||
|
6,
|
||||||
|
)
|
||||||
|
assert round(analysis["yes"]["quarter_kelly"], 6) == round(
|
||||||
|
((0.62 - 0.52) / (1.0 - 0.52)) / 4.0,
|
||||||
|
6,
|
||||||
|
)
|
||||||
|
assert abs(analysis["no"]["edge"] - -0.07) < 0.000001
|
||||||
|
assert analysis["lock"]["available"] is True
|
||||||
|
assert round(analysis["lock"]["edge"], 6) == 0.03
|
||||||
|
assert analysis["best_side"] == "yes"
|
||||||
|
|
||||||
|
|
||||||
def test_build_top_temperature_buckets_dedupes_same_temperature():
|
def test_build_top_temperature_buckets_dedupes_same_temperature():
|
||||||
layer = PolymarketReadOnlyLayer()
|
layer = PolymarketReadOnlyLayer()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
from src.data_collection.polymarket_ws_cache import PolymarketWsQuoteCache
|
||||||
|
|
||||||
|
|
||||||
|
def test_ws_cache_parses_best_bid_ask_event():
|
||||||
|
cache = PolymarketWsQuoteCache(enabled=True, quote_ttl_sec=30)
|
||||||
|
|
||||||
|
cache.subscribe(["asset-1"])
|
||||||
|
cache._handle_message(
|
||||||
|
{
|
||||||
|
"event_type": "best_bid_ask",
|
||||||
|
"asset_id": "asset-1",
|
||||||
|
"best_bid": "0.41",
|
||||||
|
"best_ask": "0.44",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
data = cache.get_market_data("asset-1")
|
||||||
|
|
||||||
|
assert data is not None
|
||||||
|
assert data["sell"] == 0.41
|
||||||
|
assert data["buy"] == 0.44
|
||||||
|
assert data["midpoint"] == 0.425
|
||||||
|
assert data["quote_source"] == "polymarket_ws"
|
||||||
|
|
||||||
|
|
||||||
|
def test_ws_cache_ignores_stale_quotes():
|
||||||
|
cache = PolymarketWsQuoteCache(enabled=True, quote_ttl_sec=1)
|
||||||
|
cache._quotes["asset-1"] = {
|
||||||
|
"asset_id": "asset-1",
|
||||||
|
"best_bid": 0.41,
|
||||||
|
"best_ask": 0.44,
|
||||||
|
"t": time.time() - 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert cache.get_market_data("asset-1") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_ws_cache_parses_price_change_side_updates():
|
||||||
|
cache = PolymarketWsQuoteCache(enabled=True, quote_ttl_sec=30)
|
||||||
|
|
||||||
|
cache._handle_message(
|
||||||
|
{
|
||||||
|
"event_type": "price_change",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"asset_id": "asset-1",
|
||||||
|
"side": "BUY",
|
||||||
|
"price": "0.48",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"asset_id": "asset-1",
|
||||||
|
"side": "SELL",
|
||||||
|
"price": "0.45",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
data = cache.get_market_data("asset-1")
|
||||||
|
|
||||||
|
assert data is not None
|
||||||
|
assert data["buy"] == 0.48
|
||||||
|
assert data["sell"] == 0.45
|
||||||
|
|
||||||
|
|
||||||
|
def test_ws_cache_parses_price_changes_key_and_book_event():
|
||||||
|
cache = PolymarketWsQuoteCache(enabled=True, quote_ttl_sec=30)
|
||||||
|
|
||||||
|
cache._handle_message(
|
||||||
|
{
|
||||||
|
"event_type": "book",
|
||||||
|
"asset_id": "asset-1",
|
||||||
|
"bids": [{"price": "0.42"}, {"price": "0.44"}],
|
||||||
|
"asks": [{"price": "0.51"}, {"price": "0.49"}],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cache._handle_message(
|
||||||
|
{
|
||||||
|
"event_type": "price_change",
|
||||||
|
"price_changes": [
|
||||||
|
{
|
||||||
|
"asset_id": "asset-1",
|
||||||
|
"side": "BUY",
|
||||||
|
"price": "0.48",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
data = cache.get_market_data("asset-1")
|
||||||
|
|
||||||
|
assert data is not None
|
||||||
|
assert data["sell"] == 0.44
|
||||||
|
assert data["buy"] == 0.48
|
||||||
|
|
||||||
|
|
||||||
|
def test_ws_cache_subscription_payloads_match_market_channel_shape():
|
||||||
|
class FakeWs:
|
||||||
|
def __init__(self):
|
||||||
|
self.messages = []
|
||||||
|
|
||||||
|
async def send(self, payload):
|
||||||
|
self.messages.append(json.loads(payload))
|
||||||
|
|
||||||
|
cache = PolymarketWsQuoteCache(enabled=True)
|
||||||
|
ws = FakeWs()
|
||||||
|
|
||||||
|
asyncio.run(cache._send_subscription(ws, ["asset-1"], initial=True))
|
||||||
|
asyncio.run(cache._send_subscription(ws, ["asset-2"], initial=False))
|
||||||
|
|
||||||
|
assert ws.messages[0] == {
|
||||||
|
"type": "market",
|
||||||
|
"assets_ids": ["asset-1"],
|
||||||
|
"custom_feature_enabled": True,
|
||||||
|
}
|
||||||
|
assert ws.messages[1] == {
|
||||||
|
"operation": "subscribe",
|
||||||
|
"assets_ids": ["asset-2"],
|
||||||
|
"custom_feature_enabled": True,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user