"""Signal-driven multi-stock strategy.""" import backtrader as bt import pandas as pd class AlphaStrategy(bt.Strategy): """Trade feeds based on precomputed ``signal`` line. Supports two builder modes: - ThresholdBuilder: per-stock threshold (passed ``(signal_value, in_position)``) - RankEqualWeightBuilder: cross-sectional ranking (passed ``{symbol: signal}`` dict) """ def __init__(self, builder): self.builder = builder def next(self): # Collect all signals signals: dict[str, float] = {} for data in self.datas: sig = data.signal[0] if not pd.isna(sig): signals[data._name] = float(sig) if not signals: return # Detect builder type: if RankEqualWeightBuilder, use cross-sectional mode from portfolio.builder import RankEqualWeightBuilder if isinstance(self.builder, RankEqualWeightBuilder): actions = self.builder.build(signals) for data in self.datas: name = data._name if name not in actions: continue action = actions[name] if action.action == "buy": self.order_target_percent(data=data, target=action.size_pct) elif action.action == "sell": self.close(data=data) else: # Legacy per-stock ThresholdBuilder for data in self.datas: name = data._name if name not in signals: continue in_position = bool(self.getposition(data).size) action = self.builder.build(signals[name], in_position) if action.action == "buy": self.order_target_percent(data=data, target=action.size_pct) elif action.action == "sell": self.close(data=data)