Prateek2001's picture
Upload backtest.py with huggingface_hub
1cca0eb verified
"""
Nifty 50 Ensemble Backtest Script
Simulates trading with the ensemble predictions.
"""
import argparse
import pandas as pd
import numpy as np
from nifty_ensemble_v2 import NiftyEnsembleV2
def backtest(df, results, threshold=0.55, commission=0.0005, slippage=0.0001):
"""
Simple backtest: go long when prob_up > threshold, short when < 1-threshold.
"""
df = df.copy()
df['proba_up'] = results['proba'][:, 1]
df['pred'] = results['pred']
df['returns'] = df['Close'].pct_change().shift(-1)
# Positions: +1 = long, -1 = short, 0 = flat
df['position'] = np.where(df['proba_up'] > threshold, 1,
np.where(df['proba_up'] < (1 - threshold), -1, 0))
# Strategy returns
df['strat_ret'] = df['position'].shift(1) * df['returns']
# Transaction costs on position changes
df['pos_change'] = df['position'].diff().abs()
df['costs'] = df['pos_change'] * (commission + slippage)
df['strat_ret_net'] = df['strat_ret'] - df['costs']
# Cumulative
df['cum_market'] = (1 + df['returns'].fillna(0)).cumprod()
df['cum_strat'] = (1 + df['strat_ret_net'].fillna(0)).cumprod()
# Metrics
valid = df['strat_ret_net'].dropna()
sharpe = valid.mean() / valid.std() * np.sqrt(252 * 375) if valid.std() > 0 else 0 # annualized for 1m
win_rate = (valid > 0).mean()
max_dd = ((df['cum_strat'].cummax() - df['cum_strat']) / df['cum_strat'].cummax()).max()
print(f"\n{'='*50}")
print("BACKTEST RESULTS")
print(f"{'='*50}")
print(f"Threshold: {threshold}")
print(f"Trades: {df['pos_change'].sum():.0f}")
print(f"Win Rate: {win_rate:.2%}")
print(f"Sharpe (ann): {sharpe:.3f}")
print(f"Max Drawdown: {max_dd:.2%}")
print(f"Final Return (strat): {(df['cum_strat'].iloc[-1] - 1):.2%}")
print(f"Final Return (buy-hold): {(df['cum_market'].iloc[-1] - 1):.2%}")
return df
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--data', required=True)
parser.add_argument('--model', required=True)
parser.add_argument('--threshold', type=float, default=0.55)
parser.add_argument('--output', default='backtest_results.csv')
args = parser.parse_args()
df = pd.read_csv(args.data, index_col='Datetime', parse_dates=True)
pipe = NiftyEnsembleV2()
pipe.load(args.model)
results = pipe.predict(df)
bt = backtest(results['df'], results, threshold=args.threshold)
bt.to_csv(args.output)
print(f"\nSaved backtest to {args.output}")
if __name__ == '__main__':
main()