Back

Maket orders not going through

Hi,

We are two first timers collaborating on an algorithm and we are running into some errors when trying to make orders. We are using:

1. Coarse filter

2. Fine fundamental filter

3. minute resolution to make intraday trading decisions in OnData()

Everything up to fineFilter() works as far as my testing went. We do return symbols to coarse and fine filter so I know that much is working. The algorithm is having issues going through with orders. I believe the problem may lie in my implementation of how we access the symbols in our universe. Because we wanted two dictionaries (one for potential long symbols and one for potential short symbols), I assigned the same symbols returned in fineFilter(), to two global list variables in the __init__() of class Coin (our algorithm name). This was because we wanted to instantiate a SymbolData object (ours named UniverseSymbolData) to use indicators for each symbol while keeping it organized and manageable. I could not figure out another way of instantiating UniverSymbolData objects for each of the symbols in our universe. I tried using the ActiveSecurities attribute but a symbol is required to acces it. Then, we use the long and short {symbol:Universe} dictionaries to extract values from the indicators and place orders on those symbols.

Currently we have OnData() set to buy everything in our universe so long as we have not yet invested in it and that the market is still open. From the debug statements, we were able to see that the algorithm does actually run up to the

self.MarketOrder

line but somehow the orders do not go through

If you could take a look at our code, we would be extremely grateful

 

 

 

import pandas as pd
import math

class Coin(QCAlgorithm):

def __init__(self):

# Global variables
self.initialized = False

# symbol data
self.ovd = {} # overvalued data
self.uvd = {} # undervalued data
self.ovs = [] # holds overvalued symbols
self.uvs = [] # holds undervalued symbols

# Coarse Filter
self.top = 450 # Only take the top equities from coarse raw

# Fine filter
self.hitop = 25 # Only take top hitop equities from overvalued
self.lotop = 25 # Only take top lotop equities from undervalued
self.himax = 0.99 # Upper limit for overvalued percentile
self.himin = 0.70 # lower limit for overvalued percentile
self.lomax = 0.30 # upper limit for undervalued percentile
self.lomin = 0.00 # lower limit for undervalued percentile
self.ratios = ["per", "pbr", "psr", "pgr", "tdr", "evr"] # filter through these ratios

def Initialize(self):

self.SetStartDate(2003, 1, 1)
self.SetEndDate(datetime.now().date() - timedelta(1))
self.SetCash(20000)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
self.UniverseSettings.Resolution = Resolution.Minute
self.AddUniverse(self.coarseFilter, self.fineFilter)

def initData(self):
aes = self.ovs + self.uvs
for symbol in aes: # instatiate UniverseSymbolData objects for all symbols in our universe
if (symbol in self.ovs):
self.ovd[symbol] = UniverseSymbolData(
symbol, self.SubscriptionManager, self.RegisterIndicator)
else:
self.uvd[symbol] = UniverseSymbolData(
symbol, self.SubscriptionManager, self.RegisterIndicator)
self.SetWarmup(timedelta(1))

def coarseFilter(self, coarse):
raw = {} # raw data holding all stocks
for eq in coarse: # iterate through equitties
if (eq.HasFundamentalData): # check for fundamental data
raw[eq] = CoarseSymbolData(eq.Symbol, self.Debug) # raw: key=eq, value=CoarseSymbolData
candidate = raw[eq] # candidate = get eq in raw
candidate.update(eq.Volume, eq.DollarVolume, # give candidate eq data
eq.AdjustedPrice, eq.EndTime, self.History)
selected = list(filter(lambda sd: (sd.selected == True), raw.values())) # get only desired eq
selected.sort(key=lambda sd: sd.dvolume, reverse=True) # sort descending
if (self.top > len(selected)):
self.top = len(selected)
return [sd.symbol for sd in selected[:self.top]] # return symbols

def fineFilter(self, fine):
raw = {}
for eq in fine: # raw: key=equity, value=FineFilterData(equity)
raw[eq] = FineSymbolData(eq, eq.Symbol)
for ratio in self.ratios: # iterate through ratios
raw = self.getPercentile(ratio, raw) # filter using ratio in list of ratios
selected = list(raw.values())
selected.sort(key=lambda sd: sd.PERatio) # sort by PE ratio
if ((self.hitop + self.lotop) > len(selected)):
self.hitop = math.ceil(len(selected) / 2)
self.lotop = math.floor(len(selected) / 2)
self.ovs = selected[len(selected) - self.hitop:]
self.uvs = selected[:self.lotop]
self.uvs = [sd.symbol for sd in self.uvs]
self.ovs = [sd.symbol for sd in self.ovs]
selected = selected[:self.lotop] + selected[len(selected) - self.hitop:] # take top 25 overvalued and undervalued
#self.avs
return [sd.symbol for sd in selected]

def getPercentile(self, ratio, pool):
eqr = {} # holds symbols mapped to given ratio (in decimal)
rts = {"ratio":[]} # list of ratios (in decimal) of pool
for eq in pool:
eqr[eq] = pool[eq].getRatio(ratio)
rts["ratio"].append(pool[eq].getRatio(ratio))
daf = pd.DataFrame(rts) # dataframe to calculate percentiles below
hmin = daf.quantile(self.himin)[0]
hmax = daf.quantile(self.himax)[0]
lmin = daf.quantile(self.lomin)[0]
lmax = daf.quantile(self.lomax)[0]
for eq in eqr:
if ((eqr[eq] < hmin) | (eqr[eq] > hmax)) & ( # if ratio does not fall in overvalue range
(eqr[eq] < lmin) | (eqr[eq] > lmax)): # and ratio does not fall in undervalue range
pool.pop(eq) # remove it from pool
return pool

def OnData(self, data):
if (self.initialized != True):
self.initialized = True
self.initData()
# for symbol in self.ovd:
# self.Debug(self.ovd[symbol].sma.Current.Value)
# self.Debug(self.ovd[symbol].wma.vsum)
# stop

# indicators
#self.sma = SimpleMovingAverage(self.SMAP)
#self.rsi = RelativeStrengthIndex(self.RSIP)
#self.atr = AverageTrueRange(self.ATRP)
#self.ema = ExponentialMovingAverage(self.EMAP)
#self.cls = SimpleMovingAverage(self.SMAP1)
#self.wma = WeightedMovingAverage(self.WMAP) # custom
#self.pvp = PivotPoint(self.PVPD) # custom


CloseTimeString = "12:00:00" # Set up pre-market close time
CloseOutTime = datetime.strptime(CloseTimeString, "%H:%M:%S")
CloseTime = datetime.time(CloseOutTime)


OpenTimeString = "10:30:00" # Set up post-market open time
OpenTradesTime = datetime.strptime(OpenTimeString, "%H:%M:%S")
OpenTime = datetime.time(OpenTradesTime)

#long comparisons
CloseOversma = 1.02
vwmaOverema = 1.04

#short comparisons
CloseUndersma = 0.98
vwmaUnderema = 0.96


# undervalued stocks
for symbol in self.uvd: #loop through undervalued
symboldata = self.uvd[symbol]
if not self.Portfolio[symbol].Invested: #if we do not own this symbol


DataSymbolTime = data[symbol].Time
DataTime = datetime.time(DataSymbolTime)

if DataTime < CloseTime: # Check to see if we are near market close

self.Debug(str(symbol) + " is long ready on " + str(DataSymbolTime))
posSize = self.CalculateOrderQuantity(symbol, 0.4) # Set Position Size
self.MarketOrder(symbol, posSize) # Market Order to buy


# overvalued stocks
for symbol in self.ovd: #loop through undervalued
symboldata = self.ovd[symbol]
if not self.Portfolio[symbol].Invested: #if we do not own this symbol



DataSymbolTime = data[symbol].Time # Get symbol trade time
DataTime = datetime.time(DataSymbolTime)

if DataTime < CloseTime: # Check to see if we are near market close
self.Debug(str(symbol) + " is short ready on " + str(DataSymbolTime))
posSize = self.CalculateOrderQuantity(symbol, -0.4) # Set Position Size
self.MarketOrder(symbol, posSize) # Market Order to buy

def OnEndOfDay(self): #triggered before end of day

#Liquidate all symbol
self.Liquidate()
self.Debug("Liquidating at end of day...")

class UniverseSymbolData(object):

def __init__(self, symbol, manager, register):
self.register = register
self.manager = manager
self.symbol = symbol
self.PRD = 10 # period is 10 minutes

# Periods
self.SMAP = 30 # Simple Moving Average periods
self.RSIP = 30 # Relative Strength Index periods
self.ATRP = 30 # Average True Range periods
self.EMAP = 5 # Exponential moving Average periods
self.CLSP = 1 # "close value" simple moving average
self.WMAP = 5 # Volume Weighted Moving Average periods (custom)
self.PVPD = 144 # 1 day Pivot Point (custom)

# indicators
self.sma = SimpleMovingAverage(self.SMAP)
self.rsi = RelativeStrengthIndex(self.RSIP)
self.atr = AverageTrueRange(self.ATRP)
self.ema = ExponentialMovingAverage(self.EMAP)
self.cls = SimpleMovingAverage(self.CLSP)
#self.wma = WeightedMovingAverage(self.WMAP) # custom
#self.pvp = PivotPoint(self.PVPD) # custom

# create consolidator and subscribe
PRDConsolidator = TradeBarConsolidator(timedelta(minutes = self.PRD))
self.manager.AddConsolidator(self.symbol, PRDConsolidator)

# register indicators
self.register(self.symbol, self.sma, PRDConsolidator)
self.register(self.symbol, self.rsi, PRDConsolidator)
self.register(self.symbol, self.atr, PRDConsolidator)
self.register(self.symbol, self.ema, PRDConsolidator)
self.register(self.symbol, self.cls, PRDConsolidator)
#self.register(self.symbol, self.wma, PRDConsolidator) #custom
#QC.RegisterIndicator(self.symbol, self.pvp,

class CoarseSymbolData(object): # this class for coarse filter equities (raw)

def __init__(self, symbol, debug):
self.p = debug
self.symbol = symbol
self.MINDvl = 5000000 # Minimum dollar volume
self.SMVMul = 1 # SMV 30 day multiplier
self.SMAMin = 1 # SMA min price
self.SMAVDS = 30 # simple moving average volume days
self.SMAVD = 1 # simple moving average volume day
self.SMAD = 1 # simple moving average day
self.SMAVA = SimpleMovingAverage(self.SMAVDS) # SMAV alternate indicator
self.SMAV = SimpleMovingAverage(self.SMAVD) # SMAV indicator
self.SMA = SimpleMovingAverage(self.SMAD) # SMA indicator
self.selected = False
self.dvolume = None
self.volume = None
self.price = None
self.time = None

def update(self, volume, dvolume, price, time, history):
self.dvolume = dvolume
self.volume = volume
self.price = price
self.time = time
hst = history(self.symbol, self.SMAVDS, Resolution.Daily)
for t, r in hst.iterrows():
self.SMAVA.Update(t[1], r["volume"])
self.checkReqs()

def checkReqs(self):
if ((self.SMA.Update(self.time, self.price)) & # check if indicators ready
(self.SMAV.Update(self.time, self.volume)) &
(self.SMAVA.IsReady)):
smava = self.SMAVA.Current.Value
smav = self.SMAV.Current.Value
sma = self.SMA.Current.Value
if ((sma >= self.SMAMin) & # sma has to be bigger than 10
(smav >= (self.SMVMul * smava)) & # 1 day smav >= 1.5 * 30 day smav
(self.dvolume > self.MINDvl)): # min 1 mill dollar volume
self.selected = True

class FineSymbolData(object):

def __init__(self, eq, symbol):
self.eq = eq
self.symbol = symbol
self.PERatio = self.eq.ValuationRatios.PERatio
self.PBRatio = self.eq.ValuationRatios.PBRatio
self.PSRatio = self.eq.ValuationRatios.PSRatio
self.PGRatio = self.eq.ValuationRatios.PEGRatio
self.TDRatio = self.eq.OperationRatios.TotalDebtEquityRatio.OneMonth
self.EVRatio = self.eq.ValuationRatios.EVToEBITDA1YearGrowth

def getRatio(self, ratio):
if (ratio == "per"):
return self.PERatio
elif (ratio == "pbr"):
return self.PBRatio
elif (ratio == "psr"):
return self.PSRatio
elif (ratio == "pgr"):
return self.PGRatio
elif (ratio == "tdr"):
return self.TDRatio
elif (ratio == "evr"):
return self.EVRatio

class WeightedMovingAverage:

def __init__(self, period):
self.lastdate = datetime.min
self.IsReady = False
self.period = period
self.pcount = 0
self.ptvsum = 0.0 # sum of price * volume
self.Value = 0.0 # indicator value
self.vsum = 0.0 # sum of volume

def IsReady(self):
if (self.pcount == self.period):
self.Value = (self.ptvsum / vsum)
self.pcount = 0
self.ptvsum = 0.0
self.vsum = 0.0
return True
return False

def Update(self, input): # input is a TradeBar object
success, volume, close = self.getData(input)
if not success:
return
self.pcount += 1
self.ptvsum += close * volume
self.vsum += volume

def getData(self, input):
if not input.IsFillForward:
return True, float(input.Volume), float(input.Close)
return False, 0.0, 0.0

 

 

 

Update Backtest







0

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.


Hi Brandon,

Welcome to QuantConnect!

Without proper indentation in the code, we couldn't copy and run your strategy, and it's hard for us to identify the issues. Could you please share a backtest or an updated code snippet with proper indentation so that we can help you debug the issues? Thank you!

0

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.


Hi Xin, 
 

Sorry, the last comment was incorrect. Use the backtest attached to this comment. 

Thanks so much for helping out! Cheers,

 

David

0


Update Backtest





0

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.


Loading...

This discussion is closed