Hi,
I am getting errors in my Algo.
Unknown datetime string format, unable to parse: CMB WI5URZHSTPBA|CMB R735QTJ8XC9X
at pandas._libs.tslibs.parsing.parse_datetime_string_with_reso
File "parsing.pyx" in parsing.pyx: line 312
The algo worked as expected before I have added possibility to buy options instead of equities.
I am sending the code since I canćt attach backtest with the error:
from AlgorithmImports import *
from System.Collections.Generic import List
import numpy as np
import pandas as pd
import statistics as stat
from scipy import stats
import decimal
class GeekyTanShark(QCAlgorithm):
def Initialize(self):
# set up
self.SetStartDate(2017, 1, 1)
self.SetEndDate(2017, 4, 1)
self.SetCash(1000000)
# init
self.Data = {}
self.volumes = {}
self.adv = {}
self.time = -1
self.rebalancing = False
self.backtestSymbolsPerDay = {}
self.current_universe = []
# PARAMTERS
self.strategy = "3ATH" # possible values: "3ATH", "ROLATH"
self.stop_loss_factor = 20 # facotr x std (*)
self.profit_take_factor = 20 # facotr x std (*)
self.breakeven = True # add breakeven option to the algo
self.longonly = False # False if we want to apply ATL
self.add_bond = False # should we invest in bond in fix proportion
self.resolution = Resolution.Minute # universe resolution
self.portfolio_const = "one_max" # How to contruct portfolio. Can be "fixed" "one_max", "pw"
self.add_linear_trend = True # should linear regression be estimated before entry
self.universe = "liq" # type of universe we use in algo. Can be: "custom", "liqvol", "manual", "liq"
if self.add_bond:
self.bond_share = 0.1 # share of bonds in portfolio
self.bond = Symbol.Create('TLT', SecurityType.Equity, Market.USA) # VFSTX, TLT
# (*) parameters very important
# UNIVERSE
self.UniverseSettings.Resolution = self.resolution
self.UniverseSettings.Leverage = 2
self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
# self.UniverseSettings.ExtendedMarketHours = True # https://www.quantconnect.com/forum/discussion/5483/consolidation-several-sets-of-symbols/p1
if self.universe == "liqvol" or self.universe == "liq":
self.min_price = 10 # minimal price of the security
self.num_coarse = 100 # number of companies to take into account, by dollar volume
self.num_coarse_vol = 200 # number of companies by volume
self.vol_width = 22 # window size for calculating sum of volatility
self.AddUniverse(self.CoarseSelectionFunction)
elif self.universe == "custom":
self.AddUniverse("my-blob-universe", self.SelectSymbols)
elif self.universe == "manual":
# tickers = ["COST", "LMT", "PGR", "SPG", "AAPL", "V", "MCO"]
# tickers = ["SPY"]
# self.symbols = [ Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers]
tickers = ["GBPUSD", "EURUSD", "AUDUSD", "USDJPY", "GBPJPY", "USDCHF"] # , "EURUSD", "AUDUSD", "USDJPY", "GBPJPY", "USDCHF"
self.symbols = [ Symbol.Create(ticker, SecurityType.Forex, Market.Oanda) for ticker in tickers]
# self.SetUniverseSelection(ManualUniverseSelectionModel(self.symbols))
self.AddUniverse(self.CoarseSelectionFunction)
# define type of prices
# self.SetSecurityInitializer(self.CustomSecurityInitializer)
self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
self.SetWarmUp(22 * 12, Resolution.Daily)
def CoarseSelectionFunction(self, coarse):
# return self.symbols
# 1) Liquid
if self.universe == "liq":
# monthly rebalancing
if self.time == self.Time.month:
self.rebalancing = False
return Universe.Unchanged
self.time = self.Time.month
self.rebalancing = True
# choose most liquid stocks with with prie greater than 10
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
filtered = [ x.Symbol for x in sortedByDollarVolume if x.Price > self.min_price and x.DollarVolume > 1000000]
return filtered[:self.num_coarse]
# 2) Liquid and low volatile
# update
if not self.adv:
for sec in coarse:
if sec in self.adv:
# Update with newest dollar volume
self.adv[sec.Symbol].Update(sec.AdjustedPrice, sec.Volume)
if self.time == self.Time.month: # and self.out_of_market:
self.rebalance = False
return Universe.Unchanged
self.rebalance = True
self.time = self.Time.month
self.step = 0
# coarse coarse
coarse = [x for x in coarse if x.HasFundamentalData and x.Price > self.min_price]
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)[:2000]
for sec in sortedByDollarVolume:
if sec not in self.adv:
# initiate a new instance of the class
self.adv[sec.Symbol] = AverageDollarVolume(self.vol_width)
# warm up
history = self.History(sec.Symbol, self.vol_width, Resolution.Daily)
if history.shape[0] == 0:
continue
for index, bar in history.loc[sec.Symbol].iterrows(): # leave the last row
self.adv[sec.Symbol].Update(bar.close, bar.volume)
# # Update with newest dollar volume
# self.adv[sec.Symbol].Update(sec.AdjustedPrice, sec.Volume)
# Sort by SMA of dollar volume and take top self.num_coarse
sortedBySMADV = sorted(self.adv.items(), key=lambda x: x[1].Value, reverse=True)[:self.num_coarse]
# sortedBySMADV = sorted(self.adv, key=lambda x: x[1].Value, reverse=True)[:self.num_coarse]
# self.Debug(f"Stocks: {sortedBySMADV[0]}")
# Sort by SMA of volatility and take top self.num_coarse
# sortedBySMADV = sorted(sortedBySMADV, key=lambda x: x[1].Vol, reverse=False)[:self.num_coarse_vol] # ? DOESNT WORK ??????????
# self.Debug(f"Stocks: {sortedBySMADV}")
# Get Symbol object (the key of dict)
self.filtered = [x[0] for x in sortedBySMADV]
# add bond to universe
# self.filtered.append(self.bond)
# self.Debug(f"first: {self.filtered[0]}")
# self.Debug(f"last: {self.filtered[-1]}")
return self.filtered
def SelectSymbols(self, date):
# if self.time == self.Time.month: # and self.out_of_market:
# self.rebalance = False
# return Universe.Unchanged
# self.rebalance = True
# self.time = self.Time.month
# self.step = 0
# handle live mode file format
if self.LiveMode:
# fetch the file from dropbox
str = self.Download("https://www.dropbox.com/s/2l73mu97gcehmh7/daily-stock-picker-live.csv?dl=1")
# if we have a file for today, return symbols, else leave universe unchanged
self.current_universe = str.split(',') if len(str) > 0 else self.current_universe
return self.current_universe
# backtest - first cache the entire file
if len(self.backtestSymbolsPerDay) == 0:
# str = self.Download("https://www.dropbox.com/s/ae1couew5ir3z9y/daily-stock-picker-backtest.csv?dl=1", headers)
str = self.Download("https://contentiobatch.blob.core.windows.net/qc-backtest/universe.csv")
for line in str.splitlines():
data = line.split(',')
self.backtestSymbolsPerDay[data[0]] = data[1:]
# index = date.strftime("%Y%m%d")
# self.current_universe = self.backtestSymbolsPerDay.get(index, self.current_universe)
# [self.Debug(x) for x in self.current_universe]
# self.current_universe = [Symbol.Create(x, SecurityType.Equity, Market.USA) for x in self.current_universe if x not in ["|", " "]]
# return self.current_universe
index = date.strftime("%Y%m%d")
if index not in self.backtestSymbolsPerDay:
return Universe.Unchanged
tickers = self.backtestSymbolsPerDay[index]
# self.current_universe = [Symbol.Create(x, SecurityType.Equity, Market.USA) for x in tickers if x not in ["|", " "]]
# [self.Debug(f"{date}: {x}") for x in self.current_universe]
self.current_universe = self.backtestSymbolsPerDay.get(index, self.current_universe)
# add bond to universe
if self.add_bond:
self.current_universe.append(self.bond.Value)
# [self.Debug(f"{x}") for x in self.current_universe]
return self.current_universe
def OnSecuritiesChanged(self, changes):
# added securities
for security in changes.AddedSecurities:
symbol = security.Symbol
if symbol not in self.Data:
self.Data[symbol] = SymbolData(self, symbol)
# action on removed securities
for security in changes.RemovedSecurities:
symbol = security.Symbol
# if symbol in self.Data:
# if self.Data.pop(symbol, None) is not None:
# self.Liquidate(symbol, 'Removed from universe')
def OnData(self, data):
# stop time is time after which we don't trade
stop_time = self.Time.replace(hour=15, minute=55)
if self.Time > stop_time:
return
# buy bond
if self.add_bond:
if not self.Portfolio[self.bond].Invested:
self.SetHoldings(self.bond, self.bond_share)
# check invested stocks
invested_long = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.IsLong] # we need this object for pw portfolio construction
invested_long_len = len(invested_long)
# update windows
for symbol in self.Data.keys():
# check if there is the data for the symbol: if not continue
if not data.Bars.ContainsKey(symbol): continue
if not data.ContainsKey(symbol): continue
if data[symbol] is None: continue
if not self.Data[symbol].close_window_day.IsReady: continue
if not self.Data[symbol].high_window_month.IsReady: continue
if not self.Data[symbol].high_window_week.IsReady: continue
# util values
close_current = data[symbol].Close
rolling_month_high = max(list(self.Data[symbol].high_window_day)[1:self.Data[symbol].high_window_day.Count])
week_high = self.Data[symbol].high_window_week[0]
month_high = self.Data[symbol].high_window_month[0]
day_high = self.Data[symbol].high_window_day[0]
momentun_1 = self.Data[symbol].close_window_month[0] / self.Data[symbol].close_window_month[1] - 1
momentun_2 = self.Data[symbol].close_window_month[1] / self.Data[symbol].close_window_month[2] - 1
momentun_3 = self.Data[symbol].close_window_month[2] / self.Data[symbol].close_window_month[3] - 1
higher_high_month_1 = self.Data[symbol].high_window_month[0] > self.Data[symbol].high_window_month[1]
higher_high_month_2 = self.Data[symbol].high_window_month[1] > self.Data[symbol].high_window_month[2]
higher_high_month_3 = self.Data[symbol].high_window_month[2] > self.Data[symbol].high_window_month[3]
higher_high_1 = self.Data[symbol].high_window_day[0] > self.Data[symbol].high_window_day[1]
higher_high_2 = self.Data[symbol].high_window_day[1] > self.Data[symbol].high_window_day[2]
higher_high_3 = self.Data[symbol].high_window_day[2] > self.Data[symbol].high_window_day[3]
# use this if we want to apply ATL
if not self.longonly:
week_low = self.Data[symbol].low_window_week[0]
month_low = self.Data[symbol].low_window_month[0]
day_low = self.Data[symbol].low_window_day[0]
lower_low_1 = self.Data[symbol].low_window_day[0] < self.Data[symbol].low_window_day[1]
lower_low_2 = self.Data[symbol].low_window_day[1] < self.Data[symbol].low_window_day[2]
lower_low_3 = self.Data[symbol].low_window_day[2] < self.Data[symbol].low_window_day[3]
lower_low_month_1 = self.Data[symbol].low_window_month[0] < self.Data[symbol].low_window_month[1]
lower_low_month_2 = self.Data[symbol].low_window_month[1] < self.Data[symbol].low_window_month[2]
lower_low_month_3 = self.Data[symbol].low_window_month[2] < self.Data[symbol].low_window_month[3]
# alpha
if self.strategy == "3ATH":
signal = close_current > week_high and (close_current / week_high - 1) < 0.1 and close_current > month_high and (close_current / month_high - 1) < 0.1 and close_current > day_high and momentun_1 > 0 and momentun_2 > 0 and momentun_3 > 0 and higher_high_1 and higher_high_2 and higher_high_3 and higher_high_month_1 and higher_high_month_2 and higher_high_month_3
# ave price for short TP
if signal:
self.Data[symbol].ath3_event_prices.append(close_current)
elif self.strategy == "ROLLATH":
signal = close_current > rolling_month_high
if not self.longonly:
signal_short = close_current < week_low and close_current < month_low and close_current < day_low and momentun_1 < 0 and momentun_2 < 0 and momentun_3 < 0 and (week_low / close_current - 1) < 0.05 and (month_low / close_current - 1) < 0.05 and lower_low_1 and lower_low_2 and lower_low_3 and higher_high_month_1 and higher_high_month_2 and higher_high_month_3
if signal_short:
self.Debug(f"SHORT {symbol} at {self.Time}")
# 3ATH
if not self.Portfolio[symbol].Invested and signal and (self.Portfolio.MarginRemaining > 5000 or self.portfolio_const == "pw"):
if self.add_linear_trend:
# linear regression calculation
y = list(self.Data[symbol].close_window_day)[1:self.Data[symbol].close_window_day.Count]
x = np.arange(len(y))
y.reverse()
y = np.array(y)
log_y = np.log(y)
slope, intercept, r_value, p_value, std_err = stats.linregress(x, log_y)
# self.Debug(f"R value: {r_value}")
if r_value < 0.5:
return
# DEBUG
self.Debug(
f"Symbol {symbol}, MinClose {close_current}, WeekHigh {week_high}, MonthHigh {month_high} DayHigh {day_high}, High1 {self.Data[symbol].high_window_day[0]}, High2 {self.Data[symbol].high_window_day[1]}, High3 {self.Data[symbol].high_window_day[2]}"
)
# get options data
contracts=self.OptionChainProvider.GetOptionContractList(symbol, self.Time)
# selects the type of option to be Call contract, then selects all contracts that meet our expiration criteria
uppertargetStrike=(close_current * (1 + 0.2))
minContractExpiry = 30
maxContractExpiry = 60
call = [x for x in contracts if x.ID.OptionRight ==OptionRight.Call and \
x.ID.StrikePrice > uppertargetStrike and \
minContractExpiry < (x.ID.Date - self.Time).days <= maxContractExpiry] # expiration not longer than 30 days
if not call:
return
self.Debug(f"Call: {call}")
#sorts contracts by closet expiring date and closest strike price (sorts in ascending order)
call = sorted(sorted(call, key = lambda x: x.ID.Date),
key = lambda x: x.ID.StrikePrice)
if len(call) == 0: continue
option = self.AddOptionContract(call[0], Resolution.Minute)
# option.PriceModel = QuantConnect.Securities.Option.OptionPriceModels.BlackScholes()
# orders
# self.Debug(f"Call: {call}")
self.Debug(f"Call 0: {option.Symbol}")
self.MarketOrder(option.Symbol, 10)
# 3ATL
elif self.longonly == False and not self.Portfolio[symbol].Invested and signal_short and self.Portfolio.MarginRemaining > 5000 and not self.Portfolio[symbol].IsShort:
if self.add_linear_trend:
# linear regression calculation
y = list(self.Data[symbol].close_window_day)[1:self.Data[symbol].close_window_day.Count]
x = np.arange(len(y))
y.reverse()
y = np.array(y)
log_y = np.log(y)
slope, intercept, r_value, p_value, std_err = stats.linregress(x, log_y)
self.Debug(f"Symbol: {symbol}, R^2 {r_value}")
if abs(r_value) < 0.75:
continue
# standard deviation
std_ = stat.stdev(list(self.Data[symbol].close_window_day)[1:self.Data[symbol].close_window_day.Count])
# bet size
confidence = abs(r_value)
if self.portfolio_const == "fixed":
if confidence > 0.75 and confidence < 0.8:
quantity = 0.5
elif confidence >= 0.8 and confidence < 0.85:
quantity = 0.55
elif confidence >= 0.85 and confidence < 0.9:
quantity = 0.6
elif confidence >= 0.9 and confidence < 0.95:
quantity = 0.65
elif confidence >= 0.95 and confidence < 0.99:
quantity = 0.7
elif confidence >= 0.99:
quantity = 0.75
quantity = self.CalculateOrderQuantity(symbol, quantity)
if (quantity * data[symbol].Close) > self.Portfolio.MarginRemaining:
quantity = (self.Portfolio.MarginRemaining / data[symbol].Close) - 1
# TP
ath3_prices_history = self.Data[symbol].ath3_event_prices
ath3_prices_history = [x for x in ath3_prices_history if x < close_current]
if ath3_prices_history:
short_tp = ath3_prices_history[-1]
else:
short_tp = data[symbol].High - (std_ * 1)
# orders
self.MarketOrder(symbol, -quantity, tag = "3ATL SHORT")
self.Data[symbol].stop_order_ticket = self.StopMarketOrder(symbol, quantity, data[symbol].High + (std_ * 1))
self.LimitOrder(symbol, quantity, short_tp)
elif self.Portfolio[symbol].Invested:
if self.breakeven:
if self.Portfolio[symbol].IsLong:
if self.Data[symbol].breakeven_set:
continue
else:
mean_daily_return = np.mean(np.abs(np.diff(np.log(np.flip(np.array(list(self.Data[symbol].close_window_day))))))) # 1% * 2, P = 100$; 100$ > 102$ > SL = 100
if (self.Portfolio[symbol].Price / self.Securities[symbol].Holdings.AveragePrice - 1) < (mean_daily_return * 2):
# drawdown = (data[symbol].Low / algorithm.Securities[symbol].Holdings.AveragePrice) - 1
# if drawdown < self.maximumDrawdownPercent:
# self.Liquidate(symbol)
continue
else:
# Updating an Order:
###### DEBUG #######
self.Debug(f"{self.Securities[symbol].Holdings.AveragePrice}")
self.Debug(f"{self.Portfolio[symbol].IsLong}")
self.Debug(f"{self.Data[symbol].stop_order_ticket}")
###### DEBUG #######
updateOrderFields = UpdateOrderFields()
# updateOrderFields.StopPrice = decimal.Decimal(self.Securities[symbol].Holdings.AveragePrice)
updateOrderFields.StopPrice = self.Securities[symbol].Holdings.AveragePrice
updateOrderFields.Tag = "Updated Stop order"
self.Data[symbol].stop_order_ticket.Update(updateOrderFields)
#
# self.StopMarketOrder(symbol, -self.Securities[symbol].Holdings.Quantity, self.Securities[symbol].Holdings.AveragePrice)
self.Data[symbol].breakeven_set = True
if self.Portfolio[symbol].IsShort:
if self.Data[symbol].breakeven_set:
continue
else:
mean_daily_return = np.mean(np.abs(np.diff(np.log(np.flip(np.array(list(self.Data[symbol].close_window_day))))))) # 1% * 2, P = 100$; 100$ > 102$ > SL = 100
if (self.Securities[symbol].Holdings.AveragePrice / self.Portfolio[symbol].Price - 1) < (mean_daily_return * 2):
continue
else:
# update stop loss
updateOrderFields = UpdateOrderFields()
# updateOrderFields.StopPrice = decimal.Decimal(self.Securities[symbol].Holdings.AveragePrice)
updateOrderFields.StopPrice = self.Securities[symbol].Holdings.AveragePrice
updateOrderFields.Tag = "Updated Stop order"
self.Data[symbol].stop_order_ticket.Update(updateOrderFields)
self.Data[symbol].breakeven_set = True
if self.portfolio_const == "pw" and len(invested_long) > 0 and len(invested_long) > invested_long_len:
self.Debug(f"len(invested_long) {len(invested_long)}")
self.Debug(f"invested_long_len {invested_long_len}")
for symbol_ in invested_long:
quantity = self.CalculateOrderQuantity(symbol_, 1 / len(invested_long))
close_current = data[symbol_].Close
if self.Portfolio[symbol_].Quantity == 0:
self.Data[symbol_].stop_loss_price = close_current - (close_current * (self.stop_loss_factor / 100))
self.StopMarketOrder(symbol_, -quantity, self.Data[symbol_].stop_loss_price, tag = "Initial stop order")
self.Data[symbol_].profit_take_price = close_current + (close_current * (self.profit_take_factor / 100))
self.LimitOrder(symbol_, -quantity, self.Data[symbol_].profit_take_price, tag = "Initial limit order")
self.SetHoldings(symbol_, 1 / len(invested_long), tag = "3ATH BUY")
elif self.Portfolio[symbol_].Quantity > 0:
self.Transactions.CancelOpenOrders(symbol_)
self.StopMarketOrder(symbol_, -quantity, self.Data[symbol_].stop_loss_price)
self.LimitOrder(symbol_, -quantity, self.Data[symbol_].profit_take_price)
self.SetHoldings(symbol_, 1 / len(invested_long), tag = "3ATH BUY")
self.Debug(self.Transactions.CancelOpenOrders(symbol_))
# # update stop loss
# updateOrderFields = UpdateOrderFields()
# updateOrderFields.StopPrice = self.Securities[symbol_].Holdings.AveragePrice
# updateOrderFields.Quantity = quantity
# updateOrderFields.Tag = "Updated Stop order"
# self.Data[symbol_].stop_order_ticket.Update(updateOrderFields)
# # update profit take
# updateOrderFields = UpdateOrderFields()
# updateOrderFields.LimitPrice = self.Securities[symbol_].Holdings.AveragePrice
# updateOrderFields.Quantity = quantity
# updateOrderFields.Tag = "Updated Limit order"
# self.Data[symbol_].limit_order_ticket.Update(updateOrderFields)
def OnOrderEvent(self, orderEvent):
order = self.Transactions.GetOrderById(orderEvent.OrderId)
if order.Status == OrderStatus.Filled:
if order.Type == OrderType.Limit or order.Type == OrderType.StopMarket or order.Type == OrderType.MarketOnOpen:
self.Transactions.CancelOpenOrders(order.Symbol)
self.Data.pop(order.Symbol.Value, None)
# if order.Status == OrderStatus.Canceled:
# self.Log(str(orderEvent))
class SymbolData(object):
def __init__(self, algorithm, symbol):
self.symbol = symbol
self.algorithm = algorithm
self.breakeven_set = False
self.stop_order_ticket = None
self.ath3_event_prices = []
# for pw
self.limit_order_ticket = None
self.stop_loss_price = None
self.profit_take_price = None
# define windows
self.close_window_day = RollingWindow[float](22)
self.high_window_day = RollingWindow[float](22)
self.low_window_day = RollingWindow[float](22)
self.volume_window_day = RollingWindow[float](22)
self.high_window_week = RollingWindow[float](5)
self.low_window_week = RollingWindow[float](5)
self.high_window_month = RollingWindow[float](5)
self.low_window_month = RollingWindow[float](5)
self.close_window_month = RollingWindow[float](5)
# consolidators
self.dayConsolidator = TradeBarConsolidator(Resolution.Daily)
self.weekConsolidator = TradeBarConsolidator(Calendar.Weekly)
self.monthConsolidator = TradeBarConsolidator(Calendar.Monthly)
# self.dayConsolidator = QuoteBarConsolidator(Resolution.Daily)
# self.weekConsolidator = QuoteBarConsolidator(Calendar.Weekly)
# self.monthConsolidator = QuoteBarConsolidator(Calendar.Monthly)
self.dayConsolidator.DataConsolidated += self.OnDataConsolidatedDaily
self.weekConsolidator.DataConsolidated += self.OnDataConsolidatedWeek
self.monthConsolidator.DataConsolidated += self.OnDataConsolidatedMonth
algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.dayConsolidator)
algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.weekConsolidator)
algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.monthConsolidator)
# warm up
history = self.algorithm.History([self.symbol], 22 * 12, Resolution.Daily)
if history.shape[0] == 0:
self.algorithm.Log('DataFrame is empty!')
return
for tuple in history.loc[self.symbol].itertuples():
tradebar = TradeBar(tuple.Index, self.symbol, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume)
# tradebar = QuoteBar(tuple.Index, self.symbol, tuple.open, tuple.high, tuple.low, tuple.close)
# tradebar.Symbol = self.symbol
self.dayConsolidator.Update(tradebar)
self.weekConsolidator.Update(tradebar)
self.monthConsolidator.Update(tradebar)
def update(self, close, high, volume):
pass
# self.close_window.Add(close)
# self.high_window.Add(high)
self.volume_window.Add(volume)
def OnDataConsolidatedDaily(self, sender, consolidated):
self.high_window_day.Add(consolidated.High)
self.low_window_day.Add(consolidated.Low)
self.close_window_day.Add(consolidated.Close)
# self.volume_window_day.Add(consolidated.Volume)
def OnDataConsolidatedWeek(self, sender, consolidated):
self.high_window_week.Add(consolidated.High)
self.low_window_week.Add(consolidated.Low)
def OnDataConsolidatedMonth(self, sender, consolidated):
self.high_window_month.Add(consolidated.High)
self.low_window_month.Add(consolidated.Low)
self.close_window_month.Add(consolidated.Close)
class SymbolDataCoarse(object):
def __init__(self, algorithm, symbol):
self.symbol = symbol
self.algorithm = algorithm
self.volume_window_day = RollingWindow[float](22)
history = self.algorithm.History([self.symbol], 22, Resolution.Hour)
if history.shape[0] == 0:
self.algorithm.Log('DataFrame is empty!')
if history.loc[self.symbol].shape[0] < 22:
self.mean_volume = 0
for time, row in history.loc[self.symbol].iterrows():
self.volume_window_day.Add(row["volume"])
self.mean_volume = self.average(list(self.volume_window_day))
def update(self, vol):
self.volume_window_day.Add(vol)
self.mean_volume = self.average(list(self.volume_window_day))
def average(self, lst):
return sum(lst) / len(lst)
class AverageDollarVolume(PythonIndicator): # Average Dollar Volume
def __init__(self, SMA):
self.dv = RollingWindow[float](SMA)
self.vol = RollingWindow[float](SMA)
self.Value = 0
self.Vol = 0
def Update(self, price, volume):
self.dv.Add(price * volume)
self.vol.Add(price)
if self.dv.IsReady and self.vol.IsReady:
self.Value = pd.Series(self.dv).mean()
self.Vol = stat.stdev(list(self.vol))
return True
return False
Louis Szeto
Hi Mislav
It seems like an error from parsing the wrong column, where LEAN expects a DateTime column but reads “CMB WI5URZHSTPBA|CMB R735QTJ8XC9X”. Maybe you'd like to check with your custom data first. You can take a look at these samples in LEAN GH repo.
Best
Louis
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Mislav Sagovac
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
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!