Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,7 +11,7 @@ try:
|
|
| 11 |
except:
|
| 12 |
pass
|
| 13 |
|
| 14 |
-
# ===
|
| 15 |
def get_strategy_presets():
|
| 16 |
return {
|
| 17 |
"Aggressive Prop Trader": {
|
|
@@ -53,6 +53,7 @@ def get_strategy_presets():
|
|
| 53 |
|
| 54 |
strategy_presets = get_strategy_presets()
|
| 55 |
|
|
|
|
| 56 |
def simulate_tp_strategy_full(starting_balance, trades_min, trades_max, weeks,
|
| 57 |
tp1_prob, tp2_prob, tp1_r, tp2_r, base_risk_pct,
|
| 58 |
profit_target=None, fatigue=0.0, trump_vol=0.0):
|
|
@@ -133,12 +134,93 @@ def simulate_tp_strategy_full(starting_balance, trades_min, trades_max, weeks,
|
|
| 133 |
}
|
| 134 |
|
| 135 |
return df, summary
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
def show_descriptions():
|
| 137 |
return pd.DataFrame([
|
| 138 |
{"Strategy": name, "Description": config["description"]}
|
| 139 |
for name, config in strategy_presets.items()
|
| 140 |
])
|
| 141 |
-
|
| 142 |
def analytics_dashboard(rank_by="EdgeCast Score"):
|
| 143 |
results = []
|
| 144 |
for name, config in strategy_presets.items():
|
|
@@ -164,6 +246,7 @@ def analytics_dashboard(rank_by="EdgeCast Score"):
|
|
| 164 |
|
| 165 |
return df[["π
Rank", "Strategy", "Final Balance", "Sharpe Ratio", "EdgeCast Score", "Max Drawdown %"]]
|
| 166 |
|
|
|
|
| 167 |
def generate_risk_matrix():
|
| 168 |
names = list(strategy_presets.keys())
|
| 169 |
scores = {
|
|
@@ -188,97 +271,11 @@ def generate_risk_matrix():
|
|
| 188 |
hovertemplate="<b>%{y}</b> vs <b>%{x}</b><br>Ξ Score: %{z:.2f}<extra></extra>"
|
| 189 |
)
|
| 190 |
return fig
|
| 191 |
-
|
| 192 |
-
def run_preset_strategy(style, fatigue=0.0, trump_vol=0.0):
|
| 193 |
-
if style not in strategy_presets:
|
| 194 |
-
return pd.DataFrame(), {}, go.Figure(), "Please select a strategy to begin."
|
| 195 |
-
|
| 196 |
-
config = strategy_presets[style]
|
| 197 |
-
df, summary = simulate_tp_strategy_full(
|
| 198 |
-
config["starting_balance"],
|
| 199 |
-
config["trades_min"],
|
| 200 |
-
config["trades_max"],
|
| 201 |
-
config["weeks"],
|
| 202 |
-
config["tp1_prob"],
|
| 203 |
-
config["tp2_prob"],
|
| 204 |
-
config["tp1_r"],
|
| 205 |
-
config["tp2_r"],
|
| 206 |
-
config["base_risk_pct"],
|
| 207 |
-
config["profit_target"],
|
| 208 |
-
fatigue=fatigue,
|
| 209 |
-
trump_vol=trump_vol
|
| 210 |
-
)
|
| 211 |
|
| 212 |
-
fig = go.Figure()
|
| 213 |
-
fig.add_trace(go.Scatter(
|
| 214 |
-
x=df["Week"], y=df["End Balance"],
|
| 215 |
-
mode="lines+markers", name=style
|
| 216 |
-
))
|
| 217 |
-
fig.update_layout(
|
| 218 |
-
title=f"{style} β Equity Curve",
|
| 219 |
-
xaxis_title="Week",
|
| 220 |
-
yaxis_title="Balance ($)"
|
| 221 |
-
)
|
| 222 |
-
|
| 223 |
-
return df, summary, fig, config["description"]
|
| 224 |
-
def run_manual_sim(starting_balance, trades_min, trades_max, weeks,
|
| 225 |
-
tp1_prob, tp2_prob, tp1_r, tp2_r, base_risk_pct, profit_target,
|
| 226 |
-
fatigue, trump_vol):
|
| 227 |
-
df, summary = simulate_tp_strategy_full(
|
| 228 |
-
starting_balance, trades_min, trades_max, weeks,
|
| 229 |
-
tp1_prob, tp2_prob, tp1_r, tp2_r, base_risk_pct,
|
| 230 |
-
profit_target, fatigue, trump_vol
|
| 231 |
-
)
|
| 232 |
-
|
| 233 |
-
fig = go.Figure()
|
| 234 |
-
fig.add_trace(go.Scatter(
|
| 235 |
-
x=df["Week"], y=df["End Balance"],
|
| 236 |
-
mode="lines+markers", name="Manual Config"
|
| 237 |
-
))
|
| 238 |
-
fig.update_layout(
|
| 239 |
-
title="Manual Config β Equity Curve",
|
| 240 |
-
xaxis_title="Week",
|
| 241 |
-
yaxis_title="Balance ($)"
|
| 242 |
-
)
|
| 243 |
-
|
| 244 |
-
return df, summary, fig
|
| 245 |
-
|
| 246 |
-
def get_manual_battle_interface():
|
| 247 |
-
return gr.Interface(
|
| 248 |
-
fn=dual_manual_battle,
|
| 249 |
-
inputs=[
|
| 250 |
-
gr.Markdown("#### βοΈ Manual Config A"),
|
| 251 |
-
gr.Slider(100, 20000, 2500, label="A: Start Balance"),
|
| 252 |
-
gr.Slider(1, 10, 3, label="A: Trades Min"),
|
| 253 |
-
gr.Slider(1, 15, 7, label="A: Trades Max"),
|
| 254 |
-
gr.Slider(1, 52, 12, label="A: Weeks"),
|
| 255 |
-
gr.Slider(0, 1, 0.3, step=0.05, label="A: TP1 %"),
|
| 256 |
-
gr.Slider(0, 1, 0.3, step=0.05, label="A: TP2 %"),
|
| 257 |
-
gr.Slider(0.1, 5.0, 1.0, step=0.1, label="A: TP1 R"),
|
| 258 |
-
gr.Slider(0.1, 20.0, 2.0, step=0.1, label="A: TP2 R"),
|
| 259 |
-
gr.Slider(0.001, 0.05, 0.01, step=0.001, label="A: Risk %"),
|
| 260 |
-
gr.Slider(0, 100000, 0, step=500, label="A: Profit Target π°"),
|
| 261 |
-
gr.Slider(0, 1, 0.0, step=0.1, label="A: Fatigue Level"),
|
| 262 |
-
gr.Slider(0, 1, 0.0, step=0.1, label="A: Trump Volatility"),
|
| 263 |
-
|
| 264 |
-
gr.Markdown("#### βοΈ Manual Config B"),
|
| 265 |
-
gr.Slider(100, 20000, 2500, label="B: Start Balance"),
|
| 266 |
-
gr.Slider(1, 10, 3, label="B: Trades Min"),
|
| 267 |
-
gr.Slider(1, 15, 7, label="B: Trades Max"),
|
| 268 |
-
gr.Slider(1, 52, 12, label="B: Weeks"),
|
| 269 |
-
gr.Slider(0, 1, 0.3, step=0.05, label="B: TP1 %"),
|
| 270 |
-
gr.Slider(0, 1, 0.3, step=0.05, label="B: TP2 %"),
|
| 271 |
-
gr.Slider(0.1, 5.0, 1.0, step=0.1, label="B: TP1 R"),
|
| 272 |
-
gr.Slider(0.1, 20.0, 2.0, step=0.1, label="B: TP2 R"),
|
| 273 |
-
gr.Slider(0.001, 0.05, 0.01, step=0.001, label="B: Risk %"),
|
| 274 |
-
gr.Slider(0, 100000, 0, step=500, label="B: Profit Target π°"),
|
| 275 |
-
gr.Slider(0, 1, 0.0, step=0.1, label="B: Fatigue Level"),
|
| 276 |
-
gr.Slider(0, 1, 0.0, step=0.1, label="B: Trump Volatility")
|
| 277 |
-
],
|
| 278 |
-
outputs=["dataframe", gr.Plot()],
|
| 279 |
-
title="π§ͺ Manual Battle Mode"
|
| 280 |
-
)
|
| 281 |
|
|
|
|
|
|
|
|
|
|
| 282 |
|
| 283 |
app = gr.TabbedInterface(
|
| 284 |
interface_list=[
|
|
@@ -295,7 +292,7 @@ app = gr.TabbedInterface(
|
|
| 295 |
title="π― Preset Strategy Mode"
|
| 296 |
),
|
| 297 |
|
| 298 |
-
# π οΈ Manual Config Tab
|
| 299 |
gr.Interface(
|
| 300 |
fn=run_manual_sim,
|
| 301 |
inputs=[
|
|
@@ -316,68 +313,21 @@ app = gr.TabbedInterface(
|
|
| 316 |
title="π οΈ Manual Config Mode"
|
| 317 |
),
|
| 318 |
|
| 319 |
-
|
| 320 |
-
def dual_manual_battle(
|
| 321 |
-
sb1, tmin1, tmax1, w1, tp1a, tp2a, r1a, r2a, risk1, pt1, fat1, trump1,
|
| 322 |
-
sb2, tmin2, tmax2, w2, tp1b, tp2b, r1b, r2b, risk2, pt2, fat2, trump2
|
| 323 |
-
):
|
| 324 |
-
df1, s1 = simulate_tp_strategy_full(sb1, tmin1, tmax1, w1, tp1a, tp2a, r1a, r2a, risk1, pt1, fat1, trump1)
|
| 325 |
-
df2, s2 = simulate_tp_strategy_full(sb2, tmin2, tmax2, w2, tp1b, tp2b, r1b, r2b, risk2, pt2, fat2, trump2)
|
| 326 |
-
|
| 327 |
-
s1["Strategy"] = "Manual A"
|
| 328 |
-
s2["Strategy"] = "Manual B"
|
| 329 |
-
|
| 330 |
-
comparison_df = pd.DataFrame([s1, s2])
|
| 331 |
-
comparison_df = comparison_df[["Strategy", "Final Balance", "Sharpe Ratio", "EdgeCast Score", "Max Drawdown %"]]
|
| 332 |
-
|
| 333 |
-
for col in ["Final Balance", "Sharpe Ratio", "EdgeCast Score"]:
|
| 334 |
-
best_val = comparison_df[col].astype(float).max()
|
| 335 |
-
comparison_df[col] = [
|
| 336 |
-
f"{val} π" if float(val) == best_val else val for val in comparison_df[col]
|
| 337 |
-
]
|
| 338 |
-
|
| 339 |
-
fig = go.Figure()
|
| 340 |
-
fig.add_trace(go.Scatter(x=df1["Week"], y=df1["End Balance"], name="Manual A"))
|
| 341 |
-
fig.add_trace(go.Scatter(x=df2["Week"], y=df2["End Balance"], name="Manual B"))
|
| 342 |
-
fig.update_layout(
|
| 343 |
-
title="βοΈ Manual Strategy Battle",
|
| 344 |
-
xaxis_title="Week",
|
| 345 |
-
yaxis_title="Balance ($)"
|
| 346 |
-
)
|
| 347 |
-
|
| 348 |
-
return comparison_df, fig
|
| 349 |
-
|
| 350 |
-
def dual_manual_battle(
|
| 351 |
-
sb1, tmin1, tmax1, w1, tp1a, tp2a, r1a, r2a, risk1, pt1, fat1, trump1,
|
| 352 |
-
sb2, tmin2, tmax2, w2, tp1b, tp2b, r1b, r2b, risk2, pt2, fat2, trump2
|
| 353 |
-
):
|
| 354 |
-
df1, s1 = simulate_tp_strategy_full(sb1, tmin1, tmax1, w1, tp1a, tp2a, r1a, r2a, risk1, pt1, fat1, trump1)
|
| 355 |
-
df2, s2 = simulate_tp_strategy_full(sb2, tmin2, tmax2, w2, tp1b, tp2b, r1b, r2b, risk2, pt2, fat2, trump2)
|
| 356 |
-
|
| 357 |
-
s1["Strategy"] = "Manual A"
|
| 358 |
-
s2["Strategy"] = "Manual B"
|
| 359 |
-
|
| 360 |
-
comparison_df = pd.DataFrame([s1, s2])
|
| 361 |
-
comparison_df = comparison_df[["Strategy", "Final Balance", "Sharpe Ratio", "EdgeCast Score", "Max Drawdown %"]]
|
| 362 |
-
|
| 363 |
-
for col in ["Final Balance", "Sharpe Ratio", "EdgeCast Score"]:
|
| 364 |
-
best_val = comparison_df[col].astype(float).max()
|
| 365 |
-
comparison_df[col] = [
|
| 366 |
-
f"{val} π" if float(val) == best_val else val for val in comparison_df[col]
|
| 367 |
-
]
|
| 368 |
-
|
| 369 |
-
fig = go.Figure()
|
| 370 |
-
fig.add_trace(go.Scatter(x=df1["Week"], y=df1["End Balance"], name="Manual A"))
|
| 371 |
-
fig.add_trace(go.Scatter(x=df2["Week"], y=df2["End Balance"], name="Manual B"))
|
| 372 |
-
fig.update_layout(title="βοΈ Manual Strategy Battle", xaxis_title="Week", yaxis_title="Balance")
|
| 373 |
-
|
| 374 |
-
return comparison_df, fig
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
# π§ͺ Manual Battle Mode (Dual Sliders + Histogram)
|
| 378 |
get_manual_battle_interface(),
|
| 379 |
|
| 380 |
-
# π
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
gr.Interface(
|
| 382 |
fn=analytics_dashboard,
|
| 383 |
inputs=gr.Dropdown(
|
|
@@ -386,10 +336,10 @@ def dual_manual_battle(
|
|
| 386 |
label="Sort leaderboard by:"
|
| 387 |
),
|
| 388 |
outputs="dataframe",
|
| 389 |
-
title="
|
| 390 |
),
|
| 391 |
|
| 392 |
-
# π
|
| 393 |
gr.Interface(
|
| 394 |
fn=show_descriptions,
|
| 395 |
inputs=[], outputs="dataframe",
|
|
@@ -400,11 +350,50 @@ def dual_manual_battle(
|
|
| 400 |
gr.Interface(
|
| 401 |
fn=generate_risk_matrix,
|
| 402 |
inputs=[], outputs=gr.Plot(),
|
| 403 |
-
title="π¬ Risk Matrix
|
| 404 |
)
|
| 405 |
],
|
| 406 |
-
tab_names=["Preset", "Manual", "Battle", "Leaderboard", "Descriptions", "Risk Matrix"],
|
| 407 |
title="EdgeCast β Strategy Simulation Suite"
|
| 408 |
)
|
| 409 |
|
| 410 |
app.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
except:
|
| 12 |
pass
|
| 13 |
|
| 14 |
+
# === STRATEGY PRESETS ===
|
| 15 |
def get_strategy_presets():
|
| 16 |
return {
|
| 17 |
"Aggressive Prop Trader": {
|
|
|
|
| 53 |
|
| 54 |
strategy_presets = get_strategy_presets()
|
| 55 |
|
| 56 |
+
# === CORE SIMULATION ENGINE ===
|
| 57 |
def simulate_tp_strategy_full(starting_balance, trades_min, trades_max, weeks,
|
| 58 |
tp1_prob, tp2_prob, tp1_r, tp2_r, base_risk_pct,
|
| 59 |
profit_target=None, fatigue=0.0, trump_vol=0.0):
|
|
|
|
| 134 |
}
|
| 135 |
|
| 136 |
return df, summary
|
| 137 |
+
|
| 138 |
+
# === HISTOGRAM SIMULATION (NEW) ===
|
| 139 |
+
def simulate_multiple_runs(config, metric="EdgeCast Score", runs=100):
|
| 140 |
+
metric_values = []
|
| 141 |
+
for _ in range(runs):
|
| 142 |
+
_, summary = simulate_tp_strategy_full(
|
| 143 |
+
config["starting_balance"],
|
| 144 |
+
config["trades_min"],
|
| 145 |
+
config["trades_max"],
|
| 146 |
+
config["weeks"],
|
| 147 |
+
config["tp1_prob"],
|
| 148 |
+
config["tp2_prob"],
|
| 149 |
+
config["tp1_r"],
|
| 150 |
+
config["tp2_r"],
|
| 151 |
+
config["base_risk_pct"],
|
| 152 |
+
config["profit_target"],
|
| 153 |
+
config["fatigue"],
|
| 154 |
+
config["trump_vol"]
|
| 155 |
+
)
|
| 156 |
+
metric_values.append(summary[metric])
|
| 157 |
+
return pd.DataFrame({metric: metric_values})
|
| 158 |
+
|
| 159 |
+
def plot_histogram(df, metric):
|
| 160 |
+
fig = px.histogram(df, x=metric, nbins=30, title=f"{metric} Distribution")
|
| 161 |
+
fig.update_layout(
|
| 162 |
+
xaxis_title=metric,
|
| 163 |
+
yaxis_title="Frequency",
|
| 164 |
+
bargap=0.1,
|
| 165 |
+
height=400
|
| 166 |
+
)
|
| 167 |
+
return fig
|
| 168 |
+
# === PART 2: PLOTTING ===
|
| 169 |
+
|
| 170 |
+
def equity_curve_plot(df, label="Equity Curve"):
|
| 171 |
+
fig = go.Figure()
|
| 172 |
+
fig.add_trace(go.Scatter(
|
| 173 |
+
x=df["Week"],
|
| 174 |
+
y=df["End Balance"],
|
| 175 |
+
mode="lines+markers",
|
| 176 |
+
name=label
|
| 177 |
+
))
|
| 178 |
+
fig.update_layout(
|
| 179 |
+
title=f"π {label}",
|
| 180 |
+
xaxis_title="Week",
|
| 181 |
+
yaxis_title="Balance ($)",
|
| 182 |
+
height=400
|
| 183 |
+
)
|
| 184 |
+
return fig
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def generate_histogram(metric="Final Balance"):
|
| 188 |
+
results = []
|
| 189 |
+
for name, config in strategy_presets.items():
|
| 190 |
+
_, summary = simulate_tp_strategy_full(**{k: v for k, v in config.items() if k != "description"})
|
| 191 |
+
summary["Strategy"] = name
|
| 192 |
+
results.append(summary)
|
| 193 |
+
|
| 194 |
+
df = pd.DataFrame(results)
|
| 195 |
+
|
| 196 |
+
if metric not in df.columns:
|
| 197 |
+
return go.Figure()
|
| 198 |
+
|
| 199 |
+
fig = px.histogram(
|
| 200 |
+
df,
|
| 201 |
+
x=metric,
|
| 202 |
+
color="Strategy",
|
| 203 |
+
barmode="overlay",
|
| 204 |
+
nbins=25,
|
| 205 |
+
title=f"π Histogram: {metric}",
|
| 206 |
+
labels={metric: metric}
|
| 207 |
+
)
|
| 208 |
+
|
| 209 |
+
fig.update_layout(
|
| 210 |
+
xaxis_title=metric,
|
| 211 |
+
yaxis_title="Frequency",
|
| 212 |
+
bargap=0.2
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
return fig
|
| 216 |
+
# === PART 3: ANALYSIS TABS ===
|
| 217 |
+
|
| 218 |
def show_descriptions():
|
| 219 |
return pd.DataFrame([
|
| 220 |
{"Strategy": name, "Description": config["description"]}
|
| 221 |
for name, config in strategy_presets.items()
|
| 222 |
])
|
| 223 |
+
|
| 224 |
def analytics_dashboard(rank_by="EdgeCast Score"):
|
| 225 |
results = []
|
| 226 |
for name, config in strategy_presets.items():
|
|
|
|
| 246 |
|
| 247 |
return df[["π
Rank", "Strategy", "Final Balance", "Sharpe Ratio", "EdgeCast Score", "Max Drawdown %"]]
|
| 248 |
|
| 249 |
+
|
| 250 |
def generate_risk_matrix():
|
| 251 |
names = list(strategy_presets.keys())
|
| 252 |
scores = {
|
|
|
|
| 271 |
hovertemplate="<b>%{y}</b> vs <b>%{x}</b><br>Ξ Score: %{z:.2f}<extra></extra>"
|
| 272 |
)
|
| 273 |
return fig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
|
| 276 |
+
def histogram_viewer_ui(metric):
|
| 277 |
+
return generate_histogram(metric)
|
| 278 |
+
# === PART 4: GRADIO INTERFACE ===
|
| 279 |
|
| 280 |
app = gr.TabbedInterface(
|
| 281 |
interface_list=[
|
|
|
|
| 292 |
title="π― Preset Strategy Mode"
|
| 293 |
),
|
| 294 |
|
| 295 |
+
# π οΈ Manual Config Tab
|
| 296 |
gr.Interface(
|
| 297 |
fn=run_manual_sim,
|
| 298 |
inputs=[
|
|
|
|
| 313 |
title="π οΈ Manual Config Mode"
|
| 314 |
),
|
| 315 |
|
| 316 |
+
# π§ͺ Manual Battle Tab
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
get_manual_battle_interface(),
|
| 318 |
|
| 319 |
+
# π Histogram Viewer
|
| 320 |
+
gr.Interface(
|
| 321 |
+
fn=histogram_viewer_ui,
|
| 322 |
+
inputs=gr.Dropdown(
|
| 323 |
+
choices=["Final Balance", "Sharpe Ratio", "EdgeCast Score", "Max Drawdown %"],
|
| 324 |
+
label="Select Metric"
|
| 325 |
+
),
|
| 326 |
+
outputs=gr.Plot(),
|
| 327 |
+
title="π Histogram Viewer"
|
| 328 |
+
),
|
| 329 |
+
|
| 330 |
+
# π
Leaderboard
|
| 331 |
gr.Interface(
|
| 332 |
fn=analytics_dashboard,
|
| 333 |
inputs=gr.Dropdown(
|
|
|
|
| 336 |
label="Sort leaderboard by:"
|
| 337 |
),
|
| 338 |
outputs="dataframe",
|
| 339 |
+
title="π
Strategy Leaderboard"
|
| 340 |
),
|
| 341 |
|
| 342 |
+
# π Descriptions
|
| 343 |
gr.Interface(
|
| 344 |
fn=show_descriptions,
|
| 345 |
inputs=[], outputs="dataframe",
|
|
|
|
| 350 |
gr.Interface(
|
| 351 |
fn=generate_risk_matrix,
|
| 352 |
inputs=[], outputs=gr.Plot(),
|
| 353 |
+
title="π¬ Risk Matrix"
|
| 354 |
)
|
| 355 |
],
|
| 356 |
+
tab_names=["Preset", "Manual", "Battle", "Histogram", "Leaderboard", "Descriptions", "Risk Matrix"],
|
| 357 |
title="EdgeCast β Strategy Simulation Suite"
|
| 358 |
)
|
| 359 |
|
| 360 |
app.launch()
|
| 361 |
+
# === PART 5: HISTOGRAM VIEWER ENGINE ===
|
| 362 |
+
|
| 363 |
+
def generate_histogram(metric="EdgeCast Score"):
|
| 364 |
+
results = []
|
| 365 |
+
for name, config in strategy_presets.items():
|
| 366 |
+
_, summary = simulate_tp_strategy_full(
|
| 367 |
+
config["starting_balance"], config["trades_min"], config["trades_max"], config["weeks"],
|
| 368 |
+
config["tp1_prob"], config["tp2_prob"], config["tp1_r"], config["tp2_r"],
|
| 369 |
+
config["base_risk_pct"], config["profit_target"], config["fatigue"], config["trump_vol"]
|
| 370 |
+
)
|
| 371 |
+
summary["Strategy"] = name
|
| 372 |
+
results.append(summary)
|
| 373 |
+
|
| 374 |
+
df = pd.DataFrame(results)
|
| 375 |
+
|
| 376 |
+
if metric not in df.columns:
|
| 377 |
+
return go.Figure()
|
| 378 |
+
|
| 379 |
+
fig = px.histogram(
|
| 380 |
+
df,
|
| 381 |
+
x=metric,
|
| 382 |
+
color="Strategy",
|
| 383 |
+
marginal="box",
|
| 384 |
+
opacity=0.7,
|
| 385 |
+
barmode="overlay",
|
| 386 |
+
title=f"π Distribution of {metric} Across Strategies"
|
| 387 |
+
)
|
| 388 |
+
|
| 389 |
+
fig.update_layout(
|
| 390 |
+
xaxis_title=metric,
|
| 391 |
+
yaxis_title="Count",
|
| 392 |
+
bargap=0.1,
|
| 393 |
+
height=500
|
| 394 |
+
)
|
| 395 |
+
|
| 396 |
+
return fig
|
| 397 |
+
|
| 398 |
+
def histogram_viewer_ui(metric):
|
| 399 |
+
return generate_histogram(metric)
|