import numpy as np
from datetime import datetime, timedelta
from System.Collections.Generic import List
from QuantConnect.Data.UniverseSelection import *
class BasicTemplateAlgorithm(QCAlgorithm):
'''Basic template algorithm simply initializes the date range and cash'''
def __init__(self):
# set the flag for rebalance
self.reb = 1
# Number of stocks to pass CoarseSelection process
self.num_coarse = 250
# Number of stocks to long/short
self.num_fine = 20
self.symbols = [] #None
self.first_month = 0
def Initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.SetStartDate(2015,10,07) #Set Start Date
self.SetEndDate(2017,12,12) #Set End Date
self.SetCash(1000) #Set Strategy Cash
self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
# Schedule the rebalance function to execute at the begining of each month
self.Schedule.On(self.DateRules.MonthStart(self.spy),
self.TimeRules.AfterMarketOpen(self.spy, 5), Action(self.rebalance))
#self.UniverseSettings.Resolution = Resolution.Daily
#self.UniverseSettings.MinimumTimeInUniverse = 0
# Add universes in which to find investments
#Warm up 200 bars for all subscribed data.
#self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash)
#self.SetBenchmark('SPY')
#self.UniverseSettings.Resolution = Resolution.Daily
#self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
# Schedule the rebalance function to execute at the begining of each month
#self.spy = self.AddEquity('SPY', Resolution.Daily).Symbol
#self.Schedule.On(self.DateRules.MonthStart(self.spy),
#self.TimeRules.AfterMarketOpen(self.spy,5), Action(self.rebalance)) #
def CoarseSelectionFunction(self, coarse):
# if the rebalance flag is not 1, return null list to save time.
if self.reb != 1:
return []
# make universe selection once a month
# drop stocks which have no fundamental data or have too low prices
selected = [x for x in coarse if (x.HasFundamentalData)
and (float(x.Price) > 5)]
sortedByDollarVolume = sorted(selected, key=lambda x: x.DollarVolume, reverse=True)
top = sortedByDollarVolume[:self.num_coarse]
return [i.Symbol for i in top]
def FineSelectionFunction(self, fine):
# return null list if it's not time to rebalance
if self.reb != 1:
return []
self.reb = 0
# drop stocks which don't have the information we need.
# you can try replacing those factor with your own factors here
filtered_fine = [x for x in fine if x.OperationRatios.OperationMargin.Value
and x.ValuationRatios.PriceChange1M
and x.ValuationRatios.BookValuePerShare]
self.Log('remained to select %d'%(len(filtered_fine)))
# rank stocks by three factor.
sortedByfactor1 = sorted(filtered_fine, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=True)
sortedByfactor2 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PriceChange1M, reverse=True)
sortedByfactor3 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True)
stock_dict = {}
# assign a score to each stock, you can also change the rule of scoring here.
for i,ele in enumerate(sortedByfactor1):
rank1 = i
rank2 = sortedByfactor2.index(ele)
rank3 = sortedByfactor3.index(ele)
score = sum([rank1*0.2,rank2*0.4,rank3*0.4])
stock_dict[ele] = score
# sort the stocks by their scores
self.sorted_stock = sorted(stock_dict.items(), key=lambda d:d[1],reverse=False)
sorted_symbol = [x[0] for x in self.sorted_stock]
# sotre the top stocks into the long_list and the bottom ones into the short_list
self.buy = [x for x in sorted_symbol[:self.num_fine]]
self.short = [x for x in sorted_symbol[-self.num_fine:]]
topFine = self.buy + self.short
return [i.Symbol for i in topFine]
#Our rebalanced method is straightforward: We first liquidate the stocks that are no longer in the long/short list, and then assign equal weight to the stocks we are going to long or short.
def rebalance(self):
# if this month the stock are not going to be long/short, liquidate it.
long_short_list = self.buy + self.short
for i in self.Portfolio.Values:
if (i.Invested) and (i.Symbol not in long_short_list):
self.Liquidate(i.Symbol)
# Assign each stock equally. Always hold 10% cash to avoid margin call
for i in self.buy:
self.SetHoldings(i,0.9/self.num_fine)
for i in self.short:
self.SetHoldings(i,-0.9/self.num_fine)
self.reb = 1
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
if not self.Portfolio.Invested:
self.SetHoldings("SPY", 1)
Jon Rogane
When I backtest the first order goes through but then:
Runtime Error: System.Exception: BacktestingRealTimeHandler.Run(): There was an error in a scheduled event SPY: MonthStart: SPY: 5 min after MarketOpen. The error was Python.Runtime.PythonException: TypeError : No method matches given arguments for SetHoldings
at QuantConnect.Scheduling.ScheduleManager+<>c__DisplayClass16_0.<On>b__0 (System.String name, System.DateTime time) [0x00000] in <256f28dd0deb4e74afc8c70a7e394ea0>:0
at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00036] in <256f28dd0deb4e74afc8c70a7e394ea0>:0 (Open Stacktrace)
Derek Tishler
Your last line is using a string vs a Symbol object to identify SPY, the error seems to be pointing to this use of a string I think?
Refering to:
self.SetHoldings("SPY", 1)
may want to try
self.SetHoldings(self.spy, 1)
Jon Rogane
Still recieving:
BacktestingRealTimeHandler.Run(): There was an error in a scheduled event SPY: MonthStart: SPY: 5 min after MarketOpen. The error was Python.Runtime.PythonException: TypeError : No method matches given arguments for SetHoldings
at QuantConnect.Scheduling.ScheduleManager+<>c__DisplayClass16_0.<On>b__0 (System.String name, System.DateTime time) [0x00000] in <256f28dd0deb4e74afc8c70a7e394ea0>:0
at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00036] in <256f28dd0deb4e74afc8c70a7e394ea0>:0 (Open Stacktrace)
Ian Worthington
SetHoldings in python wants a string, so can you first just replace your SetHoldings with just
SetHoldings("SPY", 1)
and check that runs.
If it runs that will confirm the error is because you are not passing in a string with your i variable.
So simple change i to i.Symbol
SetHoldings(i.Symbol, 1)Jon Rogane
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!