Prompt Details
Model
Chat - (gpt-5.6)
Token size
1,209
Example input
[STRATEGY_LOGIC_OR_CODE]: Buy BTC when 20 EMA crosses above 50 EMA and RSI(14) > 50. Sell/Close when 20 EMA crosses below 50 EMA. Position sizing 100% equity, Long only.
[ASSET_CLASS_AND_TICKER]: BTC/USDT
[BACKTEST_FRAMEWORK]: Pandas/NumPy Vectorized
[SLIPPAGE_AND_FEES]: 0.05% Taker Fee, 0.02% Slippage per side
Example output
### Section 1: Quantitative Logic Decomposition & Strategy Architecture
- Target Asset: BTC/USDT (Cryptocurrency, 24/7 continuous market)
- Framework: High-Performance Vectorized Pandas / NumPy
- Strategy Classification: Dual EMA Trend Following with Momentum Confirmation
- Entry Vector: crossover(EMA_20, EMA_50) AND RSI_14 > 50
- Exit Vector: crossunder(EMA_20, EMA_50)
- Execution Model: Long-only, 100% compounding equity, market orders executed strictly at next bar Open (t+1)
Quantitative Assumptions Requiring Confirmation:
- 100% equity reinvestment assumes zero external cash-drag and no leverage liquidation constraints.
---
### Section 2: Backtest Hygiene & Bias Prevention Audit Table
| Modeling Factor | Risk Category | Severity | Preventive Implementation | Quantitative Impact |
| :--- | :--- | :--- | :--- | :--- |
| Execution Timing | Lookahead Bias | Critical | Shifted signal series by 1 bar (signal.shift(1)) for t+1 Open execution alignment | Prevents impossible fills at the exact bar close that generated the signal. |
| Transaction Friction | Cost Modeling Gap | High | Deducted 0.07% (0.05% fee + 0.02% slippage) via df.attrs metadata binding | Enforces Single Source of Truth for friction across backtest and Monte Carlo engine. |
| Momentum Lookback | Overfitting Risk | Medium | Enforced standard institutional parameters (EMA 20/50, RSI 14) | Minimizes curve-fitting to single market regimes. |
| Missing Data Gaps | Data Integrity | Low | Implemented forward-fill (ffill()) and dropped leading NaN warmup bars | Ensures stable indicator convergence before signal generation. |
---
### Section 3: Production-Grade Python Backtesting Code
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def generate_synthetic_data(n_bars=1000, start_price=30000.0, seed=42):
np.random.seed(seed)
returns = np.random.normal(0.0005, 0.02, n_bars)
price_path = start_price * np.cumprod(1 + returns)
dates = pd.date_range(start="2023-01-01", periods=n_bars, freq="4h")
df = pd.DataFrame({
"timestamp": dates,
"open": price_path * (1 + np.random.uniform(-0.005, 0.005, n_bars)),
"high": price_path * (1 + np.random.uniform(0.005, 0.015, n_bars)),
"low": price_path * (1 - np.random.uniform(0.005, 0.015, n_bars)),
"close": price_path,
"volume": np.random.uniform(100, 5000, n_bars)
}).set_index("timestamp")
return df
def calculate_rsi(series, period=14):
delta = series.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / (loss + 1e-10)
return 100 - (100 / (1 + rs))
def run_backtest(df, fee_rate=0.0005, slippage_rate=0.0002):
# 1. Feature Engineering
df["ema_fast"] = df["close"].ewm(span=20, adjust=False).mean()
df["ema_slow"] = df["close"].ewm(span=50, adjust=False).mean()
df["rsi"] = calculate_rsi(df["close"], 14)
# 2. Raw Signal Generation (at bar close t)
crossover = (df["ema_fast"] > df["ema_slow"]) & (df["ema_fast"].shift(1) <= df["ema_slow"].shift(1))
crossunder = (df["ema_fast"] < df["ema_slow"]) & (df["ema_fast"].shift(1) >= df["ema_slow"].shift(1))
df["raw_signal"] = 0
df.loc[crossover & (df["rsi"] > 50), "raw_signal"] = 1
df.loc[crossunder, "raw_signal"] = -1
# Propagate position state (modern pandas 2.1+ syntax)
df["position"] = df["raw_signal"].replace(0, np.nan).ffill().shift(1).fillna(0)
df["position"] = df["position"].apply(lambda x: 1 if x == 1 else 0)
# 3. Execution & Returns Accounting (Single Source of Truth for friction)
total_friction = fee_rate + slippage_rate
df.attrs["total_friction"] = total_friction
df["asset_return"] = df["open"].pct_change().shift(-1)
df["trade_executed"] = df["position"].diff().abs().fillna(0)
df["strategy_return"] = (df["position"] * df["asset_return"]) - (df["trade_executed"] * total_friction)
df["equity_curve"] = (1 + df["strategy_return"].fillna(0)).cumprod()
return df
# Execution
data = generate_synthetic_data()
results = run_backtest(data)
---
### Section 4: Institutional Risk Matrix & Monte Carlo Simulation Engine
def extract_round_trip_trades(df):
friction = df.attrs.get("total_friction", 0.0)
pos = df["position"].values
opens = df["open"].values
trades = []
in_pos = False
entry_idx = 0
for i in range(len(pos)):
if not in_pos and pos[i] == 1:
in_pos = True
entry_idx = i
elif in_pos and pos[i] == 0:
in_pos = False
raw_ret = (opens[i] - opens[entry_idx]) / opens[entry_idx]
net_ret = raw_ret - (2 * friction)
trades.append(net_ret)
return np.array(trades) if len(trades) > 0 else np.array([0.0])
def compute_risk_matrix(df, periods_per_year=2190): # 4-hour bars: 365 * 6
strat_ret = df["strategy_return"].dropna()
total_return = (df["equity_curve"].iloc[-1] - 1) * 100
cagr = ((df["equity_curve"].iloc[-1]) ** (periods_per_year / len(df)) - 1) * 100
mean_ret = strat_ret.mean() * periods_per_year
std_ret = strat_ret.std() * np.sqrt(periods_per_year)
sharpe = mean_ret / (std_ret + 1e-10)
downside_std = strat_ret[strat_ret < 0].std() * np.sqrt(periods_per_year)
sortino = mean_ret / (downside_std + 1e-10)
cum_max = df["equity_curve"].cummax()
drawdown = (df["equity_curve"] - cum_max) / cum_max
max_drawdown = drawdown.min() * 100
calmar = cagr / (abs(max_drawdown) + 1e-10)
print("===== Institutional Risk Performance Matrix =====")
print(f"Total Return: {total_return:.2f}%")
print(f"Annualized CAGR: {cagr:.2f}%")
print(f"Sharpe Ratio: {sharpe:.2f}")
print(f"Sortino Ratio: {sortino:.2f}")
print(f"Max Drawdown (MDD): {max_drawdown:.2f}%")
print(f"Calmar Ratio: {calmar:.2f}")
def monte_carlo_stress_test(df, iterations=1000, ruin_threshold=-0.25):
round_trip_trades = extract_round_trip_trades(df)
n_trades = len(round_trip_trades)
simulated_drawdowns = []
ruin_count = 0
for _ in range(iterations):
resampled_trades = np.random.choice(round_trip_trades, size=n_trades, replace=True)
resampled_equity = np.cumprod(1 + resampled_trades)
cum_max = np.maximum.accumulate(resampled_equity)
dd = (resampled_equity - cum_max) / cum_max
max_dd = np.min(dd)
simulated_drawdowns.append(max_dd)
if max_dd <= ruin_threshold:
ruin_count += 1
mdd_95_ci = np.percentile(simulated_drawdowns, 5) * 100
ruin_prob = (ruin_count / iterations) * 100
print("\n===== Monte Carlo 1,000-Iteration Stress Test (Trade-by-Trade) =====")
print(f"Sampled Round-Trip Trades: {n_trades}")
print(f"95% Worst-Case Drawdown: {mdd_95_ci:.2f}%")
print(f"Probability of Ruin ({ruin_threshold*100:.0f}% DD): {ruin_prob:.2f}%")
compute_risk_matrix(results)
monte_carlo_stress_test(results)
---
### Section 5: Optimization Roadmap, Execution Checklist & Quantitative Disclaimer
* ( ) Verification in Python: Run script in Jupyter Notebook / VSCode with pandas, numpy, and matplotlib.
* ( ) Out-of-Sample (OOS) Testing: Partition dataset into 70% In-Sample training and 30% Out-of-Sample verification.
* ( ) Parameter Sensitivity Analysis: Test EMA combinations (15/45, 20/50, 25/60) to confirm stability against parameter cliffs.
* ( ) Live Slippage Calibration: Re-calibrate slippage assumptions based on actual broker fill logs.
⚠️ Quantitative Risk Disclaimer: Past backtested performance, simulated alpha, and Monte Carlo confidence intervals do not guarantee future live trading results. Live execution involves slippage, latency, liquidity constraints, and structural regime shifts not fully captured in historical simulations. Always perform walk-forward testing and paper trading before deploying capital.
By purchasing this prompt, you agree to our terms of service
GPT-5.6
Transform trading ideas or Pine Script strategies into production-ready, institutional-grade Python backtesting engines (VectorBT, Pandas, or Backtrader). This prompt strictly enforces zero-lookahead bias (t+1 open fills), models realistic slippage and fees using a single source of truth, generates complete execution code, computes a full risk performance matrix (Sharpe, Sortino, Calmar, Max Drawdown), and runs 1,000-iteration round-trip Monte Carlo stress tests.
...more
Added 3 weeks ago
