Overall Statistics |
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
#region imports from AlgorithmImports import * #endregion class CommodityMomentumAlphaModel(AlphaModel): def __init__(self): self.commodity_symbol = None self.commodity_ppo = None self.last_update_time = datetime.min self.consolidator = None self.high_threshold = 0.1 # Example threshold for high positive PPO self.low_threshold = -0.1 # Example threshold for high negative PPO self.insights = [] # Store insights self.min = 1 # Consolidate minute data into 1-minute bars self.ppo_values = [] # List to store PPO values def Update(self, algorithm, data): insights = [] # Only update once every minute if (algorithm.Time - self.last_update_time).total_seconds() < 60 * self.min: return insights self.last_update_time = algorithm.Time # Add the commodity future, e.g., Crude Oil WTI if self.commodity_symbol is None: future = algorithm.AddFuture(Futures.Energies.CrudeOilWTI, Resolution.Minute) self.commodity_symbol = future.Symbol # Consolidate minute data into 1-minute bars self.consolidator = TradeBarConsolidator(timedelta(minutes=self.min)) algorithm.SubscriptionManager.AddConsolidator(self.commodity_symbol, self.consolidator) # Register the PPO indicator to the 1-minute consolidated data self.commodity_ppo = PercentagePriceOscillator(10, 20, MovingAverageType.SIMPLE) algorithm.RegisterIndicator(self.commodity_symbol, self.commodity_ppo, self.consolidator) # Update the PPO with the latest data if self.commodity_ppo.IsReady: ppo_value = self.commodity_ppo.Current.Value self.ppo_values.append(ppo_value) algorithm.Plot("PPO", "Value", ppo_value) # Generate insights based on the PPO value and defined thresholds if ppo_value > self.high_threshold: insights.append(Insight.Price(self.commodity_symbol, timedelta(minutes=self.min), InsightDirection.Up)) elif ppo_value < self.low_threshold: insights.append(Insight.Price(self.commodity_symbol, timedelta(minutes=self.min), InsightDirection.Down)) else: insights.append(Insight.Price(self.commodity_symbol, timedelta(minutes=self.min), InsightDirection.Flat)) self.insights = insights return insights def OnSecuritiesChanged(self, algorithm, changes): for security in changes.RemovedSecurities: if security.Symbol == self.commodity_symbol: algorithm.SubscriptionManager.RemoveConsolidator(security.Symbol, self.consolidator) self.commodity_symbol = None for security in changes.AddedSecurities: if security.Symbol == self.commodity_symbol: self._register_indicator(algorithm, security) def _register_indicator(self, algorithm, security): security.consolidator = TradeBarConsolidator(timedelta(minutes=10)) algorithm.SubscriptionManager.AddConsolidator(security.Symbol, security.consolidator) algorithm.RegisterIndicator(security.Symbol, security.indicator, security.consolidator) def OnEndOfAlgorithm(self): # Optional: Save PPO values to a file (in a way that works with QuantConnect environment) ppo_df = pd.DataFrame(self.ppo_values, columns=['PPO']) algorithm.Log("PPO values saved at the end of algorithm")
# region imports from AlgorithmImports import * from CommodityMomentumAlphaModel import CommodityMomentumAlphaModel # endregion class PensiveBlackFrog(QCAlgorithm): def initialize(self): self.set_start_date(2024, 1, 1) self.set_cash(100000) self.future = self.AddFuture(Futures.Energies.CrudeOilWTI,Resolution.MINUTE) self.future.SetFilter(0, 180) # Set filter for front month contracts # Set benchmark to Crude Oil price self.SetBenchmark(self.future.Symbol) # Set up ATR indicator for the consolidated data self.atrConsolidator = TradeBarConsolidator(timedelta(minutes=10)) self.atr = self.ATR(self.future.Symbol, 14, MovingAverageType.Wilders) self.RegisterIndicator(self.future.Symbol, self.atr, self.atrConsolidator) self.SubscriptionManager.AddConsolidator(self.future.Symbol, self.atrConsolidator) # Set up the commodity momentum alpha model self.alpha_model = CommodityMomentumAlphaModel() self.AddAlpha(self.alpha_model) # Track positions to avoid overtrading self.currently_long = False self.SetWarmUp(timedelta(2)) # Warm up the algorithm with x days of data # Track positions to avoid overtrading self.currently_long = False self.currently_short = False self.SetWarmUp(timedelta(days=2)) # Warm up the algorithm with x days of data self.stopMarketOrderTicket = None self.takeProfitOrderTicket = None self.opening_bar = None def OnData(self, data: Slice): if self.IsWarmingUp: return for chain in data.FutureChains: contracts = sorted(chain.Value, key=lambda x: x.Expiry) if len(contracts) == 0: continue front_contract = contracts[0] future_symbol = front_contract.Symbol # Ensure we have data for the front contract if future_symbol not in data.Bars: continue last_close = data.Bars[future_symbol].Close atr_value = self.atr.Current.Value # self.Debug(f"ATR Value: {atr_value}") # Debug the ATR value if self.alpha_model.insights: for insight in self.alpha_model.insights: # self.Debug(f"Insight: {insight} - Last Close: {last_close} - ATR: {atr_value}") pass # if self.opening_bar is not None: # if future_symbol in data.Bars: # bar = data.Bars[future_symbol] # last_close = bar.Close # if last_close > self.opening_bar.High: # # Check existing insights and position # if self.alpha_model.insights: # for insight in self.alpha_model.insights: # if insight.Direction == InsightDirection.Up: # atr_value = self.atr.Current.Value # self.Debug(f"ATR Value: {atr_value}") # stop_loss_level = last_close - atr_value # take_profit_level = last_close + atr_value * 1.2 # # Set holdings only if we don't already have a position # if not self.Portfolio[future_symbol].Invested: # self.SetHoldings(future_symbol, -0.1) # self.stop_loss_level = stop_loss_level # self.take_profit_level = take_profit_level # self.entry_price = last_close # else: # # Update stop loss and take profit levels # self.stop_loss_level = max(self.stop_loss_level, stop_loss_level) # self.take_profit_level = min(self.take_profit_level, take_profit_level) # # Exit conditions # if future_symbol in self.Portfolio and self.Portfolio[future_symbol].Invested: # invested_symbol = self.Portfolio[future_symbol] # if future_symbol in data.Bars: # last_close = data.Bars[future_symbol].Close # if last_close <= self.stop_loss_level or last_close >= self.take_profit_level: # self.Liquidate(future_symbol) # self.Debug(f"Exited position in {future_symbol} at {last_close} due to stop loss or take profit.") # # Check if the insight direction has changed # if not any(insight.Direction == InsightDirection.Up for insight in self.alpha_model.insights): # self.Liquidate(future_symbol) # self.Debug(f"Exited position in {future_symbol} due to change in insight direction.")