| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe 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 2.351 Tracking Error 0.152 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
#region imports
from AlgorithmImports import *
#endregion
from datetime import timedelta
import numpy as np
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Brokerages import *
from QuantConnect.Data import *
from QuantConnect.Data.Market import *
from QuantConnect.Orders import *
from QuantConnect.Securities import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Selection import *
class MeanReversionAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 1, 1)
self.SetEndDate(2022, 1, 31)
self.SetCash(100000)
self.SetBrokerageModel(BrokerageName.QuantConnectBrokerage, AccountType.Margin)
self.UniverseSettings.Resolution = Resolution.Daily
self.SetAlpha(MeanReversionAlphaModel())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.01))
self.Log("Algorithm initialized.")
# Add symbols to the universe
self.symbol = 'ZL' # CBOT Soybean Oil futures symbol
# self.AddFutureContract(Futures.Grains.SoybeanOil, timedelta(days=30))
# self.AddFutureContract(Futures.Grains.SoybeanOil, timedelta(days=60))
def OnData(self, data):
self.Log("Received new data.")
insights = []
for symbol, symbolData in self.symbolDataBySymbol.items():
if not data.Bars.ContainsKey(symbol) or not symbolData.IsReady:
continue
price = data.Bars[symbol].Close
symbolData.Update(price)
if symbolData.IsOversold():
insights.append(Insight.Price(symbol, timedelta(minutes=1), InsightDirection.Up))
elif symbolData.IsOverbought():
insights.append(Insight.Price(symbol, timedelta(minutes=1), InsightDirection.Down))
self.EmitInsights(insights)
def OnSecuritiesChanged(self, changes):
for security in changes.RemovedSecurities:
symbolData = self.symbolDataBySymbol.pop(security.Symbol, None)
if symbolData is not None:
symbolData.Dispose()
addedSymbols = [x.Symbol for x in changes.AddedSecurities if x.Symbol not in self.symbolDataBySymbol]
history = self.History(addedSymbols, 20, Resolution.Daily)
for symbol in addedSymbols:
symbolData = SymbolData(symbol, 20, history)
self.symbolDataBySymbol[symbol] = symbolData
def OnOrderEvent(self, orderEvent):
self.Log(f"Order event: {orderEvent}")
def OnEndOfAlgorithm(self):
self.Log("Algorithm ended.")
class MeanReversionAlphaModel(AlphaModel):
def __init__(self, lookback=20):
self.lookback = lookback
self.symbolDataBySymbol = {}
def Update(self, algorithm, data):
insights = []
for symbol, symbolData in self.symbolDataBySymbol.items():
if not data.Bars.ContainsKey(symbol) or not symbolData.IsReady:
continue
price = data.Bars[symbol].Close
symbolData.Update(price)
if symbolData.IsOversold():
insights.append(Insight.Price(symbol, timedelta(minutes=1), InsightDirection.Up))
elif symbolData.IsOverbought():
insights.append(Insight.Price(symbol, timedelta(minutes=1), InsightDirection.Down))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
for security in changes.RemovedSecurities:
symbolData = self.symbolDataBySymbol.pop(security.Symbol, None)
if symbolData is not None:
symbolData.Dispose()
addedSymbols = [x.Symbol for x in changes.AddedSecurities if x.Symbol not in self.symbolDataBySymbol]
history = algorithm.History(addedSymbols, self.lookback, Resolution.Daily)
for symbol in addedSymbols:
symbolData = SymbolData(symbol, self.lookback, history)
self.symbolDataBySymbol[symbol] = symbolData
class SymbolData:
def __init__(self, symbol, lookback, history):
self.symbol = symbol
self.lookback = lookback
self.history = history
self.prices = []
self.IsReady = False
def Update(self, price):
self.prices.append(price)
if len(self.prices) > self.lookback:
self.prices.pop(0)
self.IsReady = True
def IsOversold(self):
if not self.IsReady:
return False
return self.prices[-1] < np.mean(self.prices) - 2 * np.std(self.prices)
def IsOverbought(self):
if not self.IsReady:
return False
return self.prices[-1] > np.mean(self.prices) + 2 * np.std(self.prices)
def Dispose(self):
pass
algorithm = MeanReversionAlgorithm()
# algorithm.Run()