zman35 commited on
Commit
51327ec
Β·
verified Β·
1 Parent(s): a808b4c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -100
app.py CHANGED
@@ -1,48 +1,62 @@
1
  import os
2
  import gradio as gr
3
  import pandas as pd
4
- import matplotlib.pyplot as plt
5
  import numpy as np
 
6
 
7
  # Disable Gradio analytics to avoid external API calls
8
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
 
 
 
 
9
 
10
- # Strategy Presets (risk_reward_ratio included per preset)
11
  strategy_presets = {
12
  "Aggressive Prop Trader": {
13
  "starting_balance": 2500, "trades_min": 5, "trades_max": 10, "weeks": 12,
14
- "tp1_prob": 0.25, "tp2_prob": 0.4, "risk_reward_ratio": 1.2, "base_risk_pct": 0.015, "profit_target": None
 
 
15
  },
16
  "Conservative Swing Trader": {
17
  "starting_balance": 2500, "trades_min": 2, "trades_max": 5, "weeks": 12,
18
- "tp1_prob": 0.35, "tp2_prob": 0.25, "risk_reward_ratio": 0.9, "base_risk_pct": 0.01, "profit_target": None
 
 
19
  },
20
  "Momentum Scalper": {
21
  "starting_balance": 2500, "trades_min": 4, "trades_max": 8, "weeks": 12,
22
- "tp1_prob": 0.3, "tp2_prob": 0.35, "risk_reward_ratio": 1.0, "base_risk_pct": 0.012, "profit_target": None
 
 
23
  },
24
  "Swing Sniper": {
25
  "starting_balance": 2500, "trades_min": 2, "trades_max": 4, "weeks": 12,
26
- "tp1_prob": 0.2, "tp2_prob": 0.5, "risk_reward_ratio": 1.1, "base_risk_pct": 0.008, "profit_target": None
 
 
27
  },
28
  "Intraday Prop Mode": {
29
  "starting_balance": 2500, "trades_min": 3, "trades_max": 7, "weeks": 12,
30
- "tp1_prob": 0.3, "tp2_prob": 0.3, "risk_reward_ratio": 1.0, "base_risk_pct": 0.02, "profit_target": None
 
 
31
  }
32
  }
33
 
 
34
  def get_scaled_risk_pct(balance, base_risk_pct):
35
  if balance < 5000: return base_risk_pct
36
  elif balance < 10000: return base_risk_pct * 0.75
37
  elif balance < 20000: return base_risk_pct * 0.5
38
  else: return base_risk_pct * 0.25
39
 
 
40
  def simulate_tp_strategy_full(starting_balance, trades_min, trades_max, weeks,
41
- tp1_prob, tp2_prob, risk_reward_ratio, base_risk_pct,
42
  profit_target=None):
43
  sl_prob = 1.0 - tp1_prob - tp2_prob
44
- tp1_r = risk_reward_ratio
45
- tp2_r = risk_reward_ratio * 2
46
  balance = starting_balance
47
  peak = balance
48
  drawdown = 0
@@ -80,16 +94,44 @@ def simulate_tp_strategy_full(starting_balance, trades_min, trades_max, weeks,
80
  peak = max(peak, balance)
81
  drawdown = max(drawdown, (peak - balance) / peak * 100)
82
  weekly_return = (balance - week_start) / week_start * 100
83
- log.append({"Week": week, "Start Balance": round(week_start, 2), "End Balance": round(balance, 2), "Weekly Return (%)": round(weekly_return, 2)})
84
-
85
- summary = {"Final Balance": round(balance, 2), "TP1 Hits": tp1_hits, "TP2 Hits": tp2_hits, "SL Hits": sl_hits,
86
- "Max Drawdown %": round(drawdown, 2), "Max Win Streak": max_win_streak, "Max Loss Streak": max_loss_streak}
 
 
 
 
 
87
  return pd.DataFrame(log), summary
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  def analytics_dashboard():
90
  leaderboard = []
91
  for name, config in strategy_presets.items():
92
- df, summary = simulate_tp_strategy_full(**config)
 
 
 
 
93
  returns = df['End Balance'].pct_change().dropna()
94
  volatility = returns.std() * np.sqrt(52)
95
  sharpe = returns.mean() / returns.std() * np.sqrt(52) if returns.std() > 0 else 0
@@ -98,93 +140,48 @@ def analytics_dashboard():
98
  max_dd = dd.max() * 100 if not dd.empty else 0
99
  final = df['End Balance'].iloc[-1] if not df.empty else config['starting_balance']
100
  score = final / (1 + max_dd)
101
- leaderboard.append({"Strategy": name, "Final Balance": round(final, 2), "Max DD %": round(max_dd, 2), "Sharpe": round(sharpe, 2), "EdgeCast Score": round(score, 2)})
 
 
 
102
  return pd.DataFrame(leaderboard).sort_values("EdgeCast Score", ascending=False).reset_index(drop=True)
103
 
104
- def battle_strategies(style1, style2):
105
- p1 = strategy_presets[style1]
106
- p2 = strategy_presets[style2]
107
- df1, s1 = simulate_tp_strategy_full(**p1)
108
- df2, s2 = simulate_tp_strategy_full(**p2)
109
-
110
- def enrich_summary(df, summary):
111
- returns = df['End Balance'].pct_change().dropna()
112
- volatility = returns.std() * np.sqrt(52)
113
- sharpe_ratio = returns.mean() / returns.std() * np.sqrt(52) if returns.std() > 0 else 0
114
- peak_balance = df['End Balance'].cummax()
115
- drawdowns = (peak_balance - df['End Balance']) / peak_balance
116
- max_drawdown = drawdowns.max() * 100 if not drawdowns.empty else 0
117
- final_balance = df['End Balance'].iloc[-1] if not df.empty else df['End Balance'].iloc[0]
118
- edgecast_score = final_balance / (1 + max_drawdown)
119
- summary["Volatility (Annualized)"] = round(volatility * 100, 2)
120
- summary["Sharpe Ratio"] = round(sharpe_ratio, 2)
121
- summary["Max Drawdown %"] = round(max_drawdown, 2)
122
- summary["EdgeCast Score"] = round(edgecast_score, 2)
123
- return summary
124
-
125
- s1 = enrich_summary(df1, s1)
126
- s2 = enrich_summary(df2, s2)
127
-
128
- def badge(score):
129
- if score >= 30000: return "πŸ’Ž Elite"
130
- elif score >= 20000: return "πŸ₯‡ Pro"
131
- elif score >= 10000: return "πŸ“ˆ Growing"
132
- else: return "🟑 Developing"
133
-
134
- badge1 = badge(s1["EdgeCast Score"])
135
- badge2 = badge(s2["EdgeCast Score"])
136
-
137
- plt.figure(figsize=(9, 5))
138
- plt.plot(df1['Week'], df1['End Balance'], label=f"{style1} ({badge1})", marker='o')
139
- plt.plot(df2['Week'], df2['End Balance'], label=f"{style2} ({badge2})", marker='o')
140
- plt.title(f"🎨 Strategy Battle – {style1} vs {style2}")
141
- plt.xlabel("Week")
142
- plt.ylabel("Account Balance")
143
- plt.grid(True)
144
- plt.legend()
145
- plt.tight_layout()
146
- plot_path = "battle_chart.png"
147
- plt.savefig(plot_path)
148
- plt.close()
149
-
150
- df_compare = pd.DataFrame({"Metric": list(s1.keys()) + ["Badge"], style1: list(s1.values()) + [badge1], style2: list(s2.values()) + [badge2]})
151
- return df_compare, plot_path
152
-
153
- # Interface Setup
154
- gr.TabbedInterface(
155
- interface_list=[
156
- gr.Interface(fn=lambda style: simulate_tp_strategy_full(**strategy_presets[style]),
157
- inputs=gr.Dropdown(choices=list(strategy_presets.keys()), label="Choose Preset Strategy"),
158
- outputs=["dataframe", "json"], title="🌟 Preset Mode"),
159
-
160
- gr.Interface(fn=simulate_tp_strategy_full,
161
- inputs=[
162
- gr.Slider(100, 20000, 2500, label="Start Balance"),
163
- gr.Slider(1, 10, 3, label="Trades Min"),
164
- gr.Slider(1, 15, 7, label="Trades Max"),
165
- gr.Slider(1, 52, 12, label="Weeks"),
166
- gr.Slider(0, 1, 0.3, step=0.05, label="TP1 %"),
167
- gr.Slider(0, 1, 0.3, step=0.05, label="TP2 %"),
168
- gr.Slider(0.1, 20, 2.0, step=0.1, label="Risk Reward Ratio"),
169
- gr.Slider(0.001, 0.05, 0.01, step=0.001, label="Risk %"),
170
- gr.Slider(0, 100000, 0, step=500, label="Profit Target πŸ’°")
171
- ],
172
- outputs=["dataframe", "json"],
173
- title="πŸ› οΈ Manual Config"),
174
-
175
- gr.Interface(fn=battle_strategies,
176
- inputs=[
177
- gr.Dropdown(choices=list(strategy_presets.keys()), label="Strategy 1"),
178
- gr.Dropdown(choices=list(strategy_presets.keys()), label="Strategy 2")
179
- ],
180
- outputs=["dataframe", gr.Image(type="filepath")],
181
- title="🎨 Battle Mode"),
182
-
183
- gr.Interface(fn=analytics_dashboard,
184
- inputs=[],
185
- outputs="dataframe",
186
- title="πŸ“Š Analytics")
187
  ],
188
- tab_names=["Preset", "Manual", "Battle", "Analytics"],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  title="EdgeCast – Strategy Simulation Suite"
190
  ).launch()
 
1
  import os
2
  import gradio as gr
3
  import pandas as pd
 
4
  import numpy as np
5
+ import plotly.graph_objs as go
6
 
7
  # Disable Gradio analytics to avoid external API calls
8
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
9
+ try:
10
+ gr.analytics_enabled = False
11
+ except AttributeError:
12
+ pass
13
 
14
+ # Strategy Presets with Descriptions
15
  strategy_presets = {
16
  "Aggressive Prop Trader": {
17
  "starting_balance": 2500, "trades_min": 5, "trades_max": 10, "weeks": 12,
18
+ "tp1_prob": 0.25, "tp2_prob": 0.4, "tp1_r": 1.2, "tp2_r": 2.4,
19
+ "base_risk_pct": 0.015, "profit_target": None,
20
+ "description": "Aggressive Prop Trader – High-frequency strategy with elevated risk. Targets larger returns with higher trade counts."
21
  },
22
  "Conservative Swing Trader": {
23
  "starting_balance": 2500, "trades_min": 2, "trades_max": 5, "weeks": 12,
24
+ "tp1_prob": 0.35, "tp2_prob": 0.25, "tp1_r": 0.9, "tp2_r": 1.8,
25
+ "base_risk_pct": 0.01, "profit_target": None,
26
+ "description": "Conservative Swing Trader – Lower trade frequency with modest risk. Prioritizes capital preservation."
27
  },
28
  "Momentum Scalper": {
29
  "starting_balance": 2500, "trades_min": 4, "trades_max": 8, "weeks": 12,
30
+ "tp1_prob": 0.3, "tp2_prob": 0.35, "tp1_r": 1.0, "tp2_r": 2.2,
31
+ "base_risk_pct": 0.012, "profit_target": None,
32
+ "description": "Momentum Scalper – Fast-paced intraday strategy capturing micro trends. Moderate volume, moderate risk."
33
  },
34
  "Swing Sniper": {
35
  "starting_balance": 2500, "trades_min": 2, "trades_max": 4, "weeks": 12,
36
+ "tp1_prob": 0.2, "tp2_prob": 0.5, "tp1_r": 1.1, "tp2_r": 3.0,
37
+ "base_risk_pct": 0.008, "profit_target": None,
38
+ "description": "Swing Sniper – Patient setup-driven trades targeting high reward-to-risk setups. Lower frequency."
39
  },
40
  "Intraday Prop Mode": {
41
  "starting_balance": 2500, "trades_min": 3, "trades_max": 7, "weeks": 12,
42
+ "tp1_prob": 0.3, "tp2_prob": 0.3, "tp1_r": 1.0, "tp2_r": 2.0,
43
+ "base_risk_pct": 0.02, "profit_target": None,
44
+ "description": "Intraday Prop Mode – Balanced approach to active trading. Good for consistent volume without extreme drawdowns."
45
  }
46
  }
47
 
48
+ # Risk scaling
49
  def get_scaled_risk_pct(balance, base_risk_pct):
50
  if balance < 5000: return base_risk_pct
51
  elif balance < 10000: return base_risk_pct * 0.75
52
  elif balance < 20000: return base_risk_pct * 0.5
53
  else: return base_risk_pct * 0.25
54
 
55
+ # Simulation core
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):
59
  sl_prob = 1.0 - tp1_prob - tp2_prob
 
 
60
  balance = starting_balance
61
  peak = balance
62
  drawdown = 0
 
94
  peak = max(peak, balance)
95
  drawdown = max(drawdown, (peak - balance) / peak * 100)
96
  weekly_return = (balance - week_start) / week_start * 100
97
+ log.append({
98
+ "Week": week, "Start Balance": round(week_start, 2),
99
+ "End Balance": round(balance, 2), "Weekly Return (%)": round(weekly_return, 2)
100
+ })
101
+
102
+ summary = {
103
+ "Final Balance": round(balance, 2), "TP1 Hits": tp1_hits, "TP2 Hits": tp2_hits, "SL Hits": sl_hits,
104
+ "Max Drawdown %": round(drawdown, 2), "Max Win Streak": max_win_streak, "Max Loss Streak": max_loss_streak
105
+ }
106
  return pd.DataFrame(log), summary
107
 
108
+ # For Preset tab
109
+ def run_preset_strategy(style):
110
+ config = strategy_presets[style]
111
+ df, summary = simulate_tp_strategy_full(
112
+ config["starting_balance"], config["trades_min"], config["trades_max"], config["weeks"],
113
+ config["tp1_prob"], config["tp2_prob"], config["tp1_r"], config["tp2_r"],
114
+ config["base_risk_pct"], config["profit_target"]
115
+ )
116
+ return df, plot_equity(df), config["description"]
117
+
118
+ # Plot equity
119
+ def plot_equity(df):
120
+ fig = go.Figure()
121
+ fig.add_trace(go.Scatter(x=df["Week"], y=df["End Balance"],
122
+ mode='lines+markers', name='Equity Curve'))
123
+ fig.update_layout(title='πŸ“ˆ Equity Curve', xaxis_title='Week', yaxis_title='Balance')
124
+ return fig
125
+
126
+ # Analytics leaderboard
127
  def analytics_dashboard():
128
  leaderboard = []
129
  for name, config in strategy_presets.items():
130
+ df, summary = simulate_tp_strategy_full(
131
+ config["starting_balance"], config["trades_min"], config["trades_max"], config["weeks"],
132
+ config["tp1_prob"], config["tp2_prob"], config["tp1_r"], config["tp2_r"],
133
+ config["base_risk_pct"], config["profit_target"]
134
+ )
135
  returns = df['End Balance'].pct_change().dropna()
136
  volatility = returns.std() * np.sqrt(52)
137
  sharpe = returns.mean() / returns.std() * np.sqrt(52) if returns.std() > 0 else 0
 
140
  max_dd = dd.max() * 100 if not dd.empty else 0
141
  final = df['End Balance'].iloc[-1] if not df.empty else config['starting_balance']
142
  score = final / (1 + max_dd)
143
+ leaderboard.append({
144
+ "Strategy": name, "Final Balance": round(final, 2), "Max DD %": round(max_dd, 2),
145
+ "Sharpe": round(sharpe, 2), "EdgeCast Score": round(score, 2)
146
+ })
147
  return pd.DataFrame(leaderboard).sort_values("EdgeCast Score", ascending=False).reset_index(drop=True)
148
 
149
+ # Gradio UI
150
+ preset_tab = gr.Interface(
151
+ fn=run_preset_strategy,
152
+ inputs=gr.Dropdown(choices=list(strategy_presets.keys()), value="Aggressive Prop Trader", label="Choose Preset Strategy"),
153
+ outputs=["dataframe", gr.Plot(), gr.Textbox(label="πŸ“˜ Strategy Description")],
154
+ title="🌟 Preset Mode"
155
+ )
156
+
157
+ manual_tab = gr.Interface(
158
+ fn=simulate_tp_strategy_full,
159
+ inputs=[
160
+ gr.Slider(100, 20000, 2500, label="Start Balance"),
161
+ gr.Slider(1, 10, 3, label="Trades Min"),
162
+ gr.Slider(1, 15, 7, label="Trades Max"),
163
+ gr.Slider(1, 52, 12, label="Weeks"),
164
+ gr.Slider(0, 1, 0.3, step=0.05, label="TP1 %"),
165
+ gr.Slider(0, 1, 0.3, step=0.05, label="TP2 %"),
166
+ gr.Slider(0.1, 20, 2.0, step=0.1, label="TP1 Reward"),
167
+ gr.Slider(0.1, 20, 4.0, step=0.1, label="TP2 Reward"),
168
+ gr.Slider(0.001, 0.05, 0.01, step=0.001, label="Risk %"),
169
+ gr.Slider(0, 100000, 0, step=500, label="Profit Target πŸ’°")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  ],
171
+ outputs=["dataframe", "json"],
172
+ title="πŸ› οΈ Manual Config"
173
+ )
174
+
175
+ analytics_tab = gr.Interface(
176
+ fn=analytics_dashboard,
177
+ inputs=[],
178
+ outputs="dataframe",
179
+ title="πŸ“Š Analytics"
180
+ )
181
+
182
+ # Main Launch
183
+ gr.TabbedInterface(
184
+ interface_list=[preset_tab, manual_tab, analytics_tab],
185
+ tab_names=["Preset", "Manual", "Analytics"],
186
  title="EdgeCast – Strategy Simulation Suite"
187
  ).launch()