intraday-btc-model-11yr / optimize_parameters.py
VenuMuvva's picture
Upload folder using huggingface_hub
8346b41 verified
Raw History Blame Contribute Delete
8.83 kB
"""
Parameter optimization for the trading strategy.
Tests different combinations of parameters to find the most profitable settings.
Uses grid search with the real Binance data.
"""
import pandas as pd
import numpy as np
import itertools
from datetime import datetime
import json
import os
from core.data_loader import load_data
from core.features import calculate_all_features
from core.signal_model import MACrossoverSignal
from core.backtester import Backtester
import config
def optimize_parameters(
data,
ma_fast_range=[10, 15, 20, 25, 30],
ma_slow_range=[30, 40, 50, 60, 80],
stop_range=[0.005, 0.008, 0.010, 0.012, 0.015],
tp_range=[0.010, 0.015, 0.020, 0.025, 0.030],
leverage_range=[1.0, 2.0, 3.0],
risk_range=[0.005, 0.01, 0.015],
volatility_filter_range=[1.5, 2.0, 2.5, 3.0],
max_combinations=100
):
"""
Run grid search optimization on parameters.
Parameters
----------
data : pd.DataFrame
Historical OHLCV data
*_range : list
Range of values to test for each parameter
max_combinations : int
Maximum combinations to test (for time management)
Returns
-------
pd.DataFrame
Results sorted by best performance
"""
print("\n" + "="*70)
print("PARAMETER OPTIMIZATION - GRID SEARCH")
print("="*70)
# Generate all parameter combinations
param_combinations = list(itertools.product(
ma_fast_range,
ma_slow_range,
stop_range,
tp_range,
leverage_range,
risk_range,
volatility_filter_range
))
# Filter valid combinations (fast < slow, tp > stop)
valid_combinations = [
(maf, mas, stop, tp, lev, risk, vf)
for maf, mas, stop, tp, lev, risk, vf in param_combinations
if maf < mas and tp > stop
]
print(f"\nTotal valid combinations: {len(valid_combinations):,}")
# Limit if too many
if len(valid_combinations) > max_combinations:
print(f"Limiting to {max_combinations} random samples for time management...")
np.random.seed(42)
indices = np.random.choice(len(valid_combinations), max_combinations, replace=False)
valid_combinations = [valid_combinations[i] for i in indices]
print(f"Testing {len(valid_combinations)} parameter combinations...\n")
results = []
for idx, (ma_fast, ma_slow, s_stop, s_tp, leverage, rho, vol_filter) in enumerate(valid_combinations):
try:
# Calculate features with these MAs
features = calculate_all_features(
data,
ma_fast=ma_fast,
ma_slow=ma_slow,
atr_period=14,
trend_window=60
)
# Generate signals
signal_model = MACrossoverSignal(volatility_threshold=vol_filter)
signals = signal_model.generate_signals(features)
# Run backtest
backtester = Backtester(
data=data,
features=features,
signals=signals,
signal_model=signal_model,
e_base=config.E_BASE,
leverage=leverage,
risk_fraction=rho,
stop_distance=s_stop,
tp_distance=s_tp,
d_max=config.D_MAX,
commission=config.COMMISSION,
slippage=config.SLIPPAGE,
verbose=False # Silent mode
)
result = backtester.run()
metrics = result['metrics']
# Store results
results.append({
'ma_fast': ma_fast,
'ma_slow': ma_slow,
'stop': s_stop,
'tp': s_tp,
'leverage': leverage,
'risk': rho,
'vol_filter': vol_filter,
'total_return': metrics['total_return_pct'],
'sharpe': metrics['sharpe_ratio'],
'max_dd': metrics['max_drawdown_pct'],
'win_rate': metrics['win_rate'],
'profit_factor': metrics['profit_factor'],
'num_trades': metrics['num_trades'],
'final_equity': metrics['total_equity']
})
# Print progress
if (idx + 1) % 10 == 0:
print(f" Tested {idx + 1}/{len(valid_combinations)} combinations...")
except Exception as e:
# Skip failed combinations
continue
# Convert to DataFrame
results_df = pd.DataFrame(results)
# Sort by total return
results_df = results_df.sort_values('total_return', ascending=False)
print(f"\n✓ Optimization complete! Tested {len(results_df)} combinations")
return results_df
def print_top_results(results_df, top_n=10):
"""Print top performing parameter sets."""
print("\n" + "="*70)
print(f"TOP {top_n} PARAMETER COMBINATIONS")
print("="*70 + "\n")
for rank, (idx, row) in enumerate(results_df.head(top_n).iterrows(), 1):
print(f"#{rank} - Return: {row['total_return']:+.2f}% | Sharpe: {row['sharpe']:.2f} | Win Rate: {row['win_rate']:.1f}%")
print(f" MA: {int(row['ma_fast'])}/{int(row['ma_slow'])} | "
f"Stop/TP: {row['stop']*100:.2f}%/{row['tp']*100:.2f}% | "
f"Lev: {row['leverage']:.1f}x | Risk: {row['risk']*100:.1f}%")
print(f" Trades: {int(row['num_trades'])} | "
f"Profit Factor: {row['profit_factor']:.2f} | "
f"Max DD: {row['max_dd']:.1f}%")
print()
def save_optimization_results(results_df, output_path):
"""Save results to CSV."""
results_df.to_csv(output_path, index=False)
print(f"✓ Saved full results to: {output_path}")
def get_best_parameters(results_df):
"""Get the best parameter set."""
best = results_df.iloc[0]
return {
'MA_FAST': int(best['ma_fast']),
'MA_SLOW': int(best['ma_slow']),
'S_STOP': best['stop'],
'S_TP': best['tp'],
'L_DEFAULT': best['leverage'],
'RHO': best['risk'],
'VOLATILITY_FILTER': best['vol_filter']
}
def main():
"""Main optimization execution."""
print("\n🔍 STRATEGY PARAMETER OPTIMIZATION")
print("="*70)
# Load data
print("\n📥 Loading Binance data...")
data = load_data(config.BTC_DATA_FILE)
print(f" Loaded {len(data):,} bars")
# Define search space (focused on likely profitable ranges)
print("\n🎯 Defining parameter search space...")
print(" MA Fast: [15, 20, 25, 30, 40]")
print(" MA Slow: [40, 50, 60, 80, 100]")
print(" Stop-Loss: [0.5%, 0.8%, 1.0%, 1.2%, 1.5%]")
print(" Take-Profit: [1.0%, 1.5%, 2.0%, 2.5%, 3.0%]")
print(" Leverage: [1x, 2x, 3x]")
print(" Risk per trade: [0.5%, 1.0%, 1.5%]")
print(" Volatility filter: [1.5, 2.0, 2.5, 3.0]")
# Run optimization
results_df = optimize_parameters(
data,
ma_fast_range=[15, 20, 25, 30, 40],
ma_slow_range=[40, 50, 60, 80, 100],
stop_range=[0.005, 0.008, 0.010, 0.012, 0.015],
tp_range=[0.010, 0.015, 0.020, 0.025, 0.030],
leverage_range=[1.0, 2.0, 3.0],
risk_range=[0.005, 0.01, 0.015],
volatility_filter_range=[1.5, 2.0, 2.5, 3.0],
max_combinations=100 # Limit for reasonable runtime
)
# Print top results
print_top_results(results_df, top_n=10)
# Save results
output_path = os.path.join(config.REPORTS_DIR, 'optimization_results.csv')
save_optimization_results(results_df, output_path)
# Get best parameters
best_params = get_best_parameters(results_df)
print("\n" + "="*70)
print("📌 RECOMMENDED PARAMETERS (Best Performance)")
print("="*70)
for param, value in best_params.items():
print(f" {param} = {value}")
# Save best params to JSON
best_params_path = os.path.join(config.REPORTS_DIR, 'best_parameters.json')
with open(best_params_path, 'w') as f:
json.dump(best_params, f, indent=2)
print(f"\n✓ Saved best parameters to: {best_params_path}")
print("\n💡 Next steps:")
print(" 1. Update config.py with the recommended parameters")
print(" 2. Run: python run_backtest.py (to verify)")
print(" 3. If profitable, proceed to live paper trading!")
print("="*70 + "\n")
if __name__ == "__main__":
main()