Premchan369 commited on
Commit
d9403f2
·
verified ·
1 Parent(s): be296ce

Upload strategy_ensemble.py

Browse files
Files changed (1) hide show
  1. strategy_ensemble.py +100 -0
strategy_ensemble.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Strategy Ensemble - Dynamic capital allocation across strategies."""
2
+ import numpy as np
3
+ import pandas as pd
4
+ from typing import Dict, List, Optional
5
+ import warnings
6
+ warnings.filterwarnings('ignore')
7
+
8
+
9
+ class StrategyEnsemble:
10
+ """Multi-strategy system with dynamic capital allocation."""
11
+
12
+ def __init__(self):
13
+ self.strategies = {
14
+ 'momentum': {'weight': 0.25, 'sharpe': 0.8, 'track_record': []},
15
+ 'mean_reversion': {'weight': 0.25, 'sharpe': 0.6, 'track_record': []},
16
+ 'arbitrage': {'weight': 0.20, 'sharpe': 1.2, 'track_record': []},
17
+ 'ml_alpha': {'weight': 0.15, 'sharpe': 1.0, 'track_record': []},
18
+ 'sentiment': {'weight': 0.10, 'sharpe': 0.5, 'track_record': []},
19
+ 'options': {'weight': 0.05, 'sharpe': 0.9, 'track_record': []}
20
+ }
21
+ self.capital = 1_000_000
22
+ self.allocation_history = []
23
+
24
+ def update_performance(self, strategy_returns: Dict[str, float]):
25
+ """Update rolling Sharpe for each strategy."""
26
+ for name, ret in strategy_returns.items():
27
+ if name in self.strategies:
28
+ self.strategies[name]['track_record'].append(ret)
29
+ # Keep last 63 days
30
+ if len(self.strategies[name]['track_record']) > 63:
31
+ self.strategies[name]['track_record'] = self.strategies[name]['track_record'][-63:]
32
+
33
+ # Update Sharpe
34
+ records = self.strategies[name]['track_record']
35
+ if len(records) > 5:
36
+ mean_ret = np.mean(records)
37
+ std_ret = np.std(records)
38
+ self.strategies[name]['sharpe'] = mean_ret / std_ret * np.sqrt(252) if std_ret > 0 else 0
39
+
40
+ def allocate_capital(self, max_weight: float = 0.35, min_weight: float = 0.02) -> Dict[str, float]:
41
+ """
42
+ Dynamic capital allocation based on:
43
+ - Recent Sharpe ratio
44
+ - Strategy correlation (for diversification)
45
+ - Risk budget
46
+ """
47
+ # Get Sharpe ratios
48
+ sharpes = {name: max(s['sharpe'], 0.1) for name, s in self.strategies.items()}
49
+
50
+ # Square Sharpe for more differentiation
51
+ weights = {name: s ** 2 for name, s in sharpes.items()}
52
+ total = sum(weights.values())
53
+
54
+ if total > 0:
55
+ weights = {name: w / total for name, w in weights.items()}
56
+ else:
57
+ n = len(weights)
58
+ weights = {name: 1.0 / n for name in weights}
59
+
60
+ # Apply constraints
61
+ for name in weights:
62
+ weights[name] = np.clip(weights[name], min_weight, max_weight)
63
+
64
+ # Renormalize
65
+ total = sum(weights.values())
66
+ weights = {name: w / total for name, w in weights.items()}
67
+
68
+ self.allocation_history.append(weights)
69
+ return weights
70
+
71
+ def allocate_dollar(self, total_capital: float, weights: Dict[str, float]) -> Dict[str, float]:
72
+ """Convert weight allocation to dollar amounts."""
73
+ return {name: total_capital * w for name, w in weights.items()}
74
+
75
+ def combine_signals(self, signals: Dict[str, np.ndarray], weights: Optional[Dict[str, float]] = None) -> np.ndarray:
76
+ """Combine signals from multiple strategies."""
77
+ if weights is None:
78
+ weights = self.allocate_capital()
79
+
80
+ n_samples = len(list(signals.values())[0])
81
+ combined = np.zeros(n_samples)
82
+
83
+ for name, signal in signals.items():
84
+ if name in weights:
85
+ combined += weights[name] * signal
86
+
87
+ return combined
88
+
89
+ def get_performance_report(self) -> pd.DataFrame:
90
+ """Generate strategy performance report."""
91
+ report = []
92
+ for name, strat in self.strategies.items():
93
+ report.append({
94
+ 'strategy': name,
95
+ 'current_weight': self.allocation_history[-1].get(name, 0) if self.allocation_history else strat['weight'],
96
+ 'sharpe': strat['sharpe'],
97
+ 'max_weight': max(a.get(name, 0) for a in self.allocation_history) if self.allocation_history else 0,
98
+ 'track_record_len': len(strat['track_record'])
99
+ })
100
+ return pd.DataFrame(report)