Hi there,
I have a strategy that uses pre-defined price data for various futures contracts that works fine, but when I update the algorithm to use the Quantconnect continuous futures, the algorithm gives an error about leverage:
Runtime Error: Futures do not allow specifying a leveraged target, since they are traded using margin which already is leveraged. Possible target buying power goes from -1 to 1, target provided is: -1.597480554358317825 in FutureMarginModel.cs:line 118
Here's the code:
+ Expand
from math import ceil
from AlgorithmImports import *
class ReturnsSignalMomentum(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 1, 1)
self.SetCash(100000)
self.ES_contract = self.AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
dataMappingMode = DataMappingMode.OpenInterest,
contractDepthOffset = 0)
self.GC_contract = self.AddFuture(Futures.Metals.Gold,
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
dataMappingMode = DataMappingMode.OpenInterest,
contractDepthOffset = 0)
self.CL_contract = self.AddFuture(Futures.Energies.CrudeOilWTI,
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
dataMappingMode = DataMappingMode.OpenInterest,
contractDepthOffset = 0)
self.symbols = [
self.ES_contract.Symbol,
self.GC_contract.Symbol,
self.CL_contract.Symbol
]
#self.symbols = [
# "CME_AD1", # Australian Dollar Futures, Continuous Contract #1
# "CME_BP1", # British Pound Futures, Continuous Contract #1
# "CME_EC1", # Euro FX Futures, Continuous Contract #1
# "CME_JY1", # Japanese Yen Futures, Continuous Contract #1
# "ICE_DX1", # US Dollar Index Futures, Continuous Contract #1
# "CME_NQ1", # E-mini NASDAQ 100 Futures, Continuous Contract #1
# "EUREX_FDAX1", # DAX Futures, Continuous Contract #1
# "CME_ES1", # E-mini S&P 500 Futures, Continuous Contract #1
# "CME_GC1", # Gold Futures, Continuous Contract
# "CME_SI1", # Silver Futures, Continuous Contract
# "ICE_CC1", # Cocoa Futures, Continuous Contract
# "ICE_KC1", # Coffee C Futures, Continuous Contract
# "ICE_SB1", # Sugar No. 11 Futures, Continuous Contract
# "CME_S1", # Soybean Futures, Continuous Contract
# "CME_W1", # Wheat Futures, Continuous Contract
# "CME_C1", # Corn Futures, Continuous Contract
# "CME_LC1", # Live Cattle Futures, Continuous Contract
# "CME_FC1", # Feeder Cattle Futures, Continuous Contract
# "CME_ZB1",
# "CME_ZQ1",
# "CME_NG1", # Natural Gas (Henry Hub) Physical Futures, Continuous Contract
# "CME_CL1",
# "ICE_O1" # Heating Oil Futures, Continuous Contract
# ]
period = 100
self.SetWarmUp(period)
self.dch = {}
self.atr = {}
for symbol in self.symbols:
#data = self.AddData(QuantpediaFutures, symbol, Resolution.Daily)
data = self.History(symbol, 252, Resolution.Daily)
#data.SetFeeModel(CustomFeeModel())
#data.SetLeverage(10)
self.dch[symbol] = self.DCH(symbol, period, Resolution.Daily)
self.atr[symbol] = self.ATR(symbol, 10, Resolution.Daily)
def OnData(self, data):
if self.IsWarmingUp: return
dollar_pos_size = {}
equity = self.Portfolio.TotalPortfolioValue
long = []
short = []
for symbol in self.symbols:
if self.Securities[symbol].GetLastData() and (self.Time.date() - self.Securities[symbol].GetLastData().Time.date()).days >= 5:
continue
if symbol not in data or not data[symbol]: continue
if not self.dch[symbol].IsReady or not self.atr[symbol].IsReady: continue
price = data[symbol].Price
atr = self.atr[symbol].Current.Value
upper_band = self.dch[symbol].UpperBand.Current.Value
lower_band = self.dch[symbol].LowerBand.Current.Value
# Close position.
if self.Portfolio[symbol].IsLong:
if price < lower_band:
#if price < (upper_band - 2*atr):
self.Liquidate(symbol)
if self.Portfolio[symbol].IsShort:
if price > upper_band:
#if price > (lower_band + 2*atr):
self.Liquidate(symbol)
# Calculate positon size.
#unit_size = (equity * 0.1 * 0.02) / (atr*4)
unit_size = (equity * 0.1 * 0.02) / (atr)
if price > upper_band:
if not self.Portfolio[symbol].IsLong:
long.append(symbol)
dollar_pos_size[symbol] = unit_size * price
elif price < lower_band:
if not self.Portfolio[symbol].IsShort:
short.append(symbol)
dollar_pos_size[symbol] = unit_size * price
# Rebalance opened positions and open new ones.
for symbol in long + short:
percentage = dollar_pos_size[symbol] / equity
if symbol in long: self.SetHoldings(symbol, percentage)
if symbol in short: self.SetHoldings(symbol, -percentage)
# Custom fee model.
class CustomFeeModel(FeeModel):
def GetOrderFee(self, parameters):
fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))
Besides changing the data source, I also changed the method to access the data from AddData to History:
#data = self.AddData(QuantpediaFutures, symbol, Resolution.Daily)
data = self.History(symbol, 252, Resolution.Daily)
Just wondering, if there is a difference between how price data is returned from AddData versus History.
Please advise.
David
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!