Back

Getting historical closing price

Hello everyone,

I'm new to Quantconnect and I feel a little lost as I still don't know how many things work after having read the documentation. I'm trying to do something very simple for my first test algorithm. It should buy AAPL if the current price is lower than the previous day's closing price and sell it if it reaches a higher price than it was bought for. But I don't know how to get that closing price so I can compare them. I get an error saying my bars object has no .close property. How to do that correctly?

Thank you very much for your help.

Kind Regards,

Christian Lauer

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.


class BasicTemplateAlgorithm(QCAlgorithm):

    def Initialize(self):
        # Set the cash we'd like to use for our backtest
        # This is ignored in live trading
        self.SetCash(100000)
        
        # Start and end dates for the backtest.
        # These are ignored in live trading.
        self.SetStartDate(2007,1,1)
        self.SetEndDate(2007,3,3)
        
        # Add assets you'd like to see
        self.aapl = self.AddEquity("aapl", Resolution.Second).Symbol
        
        self.bars = self.History("aapl", TimeSpan.FromDays(3), Resolution.Daily)
        
        self.SetWarmUp(200)
        

    def OnData(self, slice):
        # Simple buy and hold template
        if not self.Portfolio.Invested and self.bars.Close[2] > self.price:
            self.SetHoldings(self.aapl, 1)
            self.Debug("numpy test >>> print numpy.pi: " + str(np.pi))
            
        if portfolio["aapl"].price < Securities["aapl"].Price:
            self.SetHoldings(self.aapl, 0)

 

0

By the description, it looks like the strategy needs to use the rolling window feature:

# In Initialize
# Creates a Rolling Window indicator to keep the 2 TradeBar
self.window = RollingWindow[TradeBar](2)

# In OnData
# Add SPY TradeBar in rollling window
self.window.Add(data["SPY"])
# Wait for windows to be ready.
if not (self.window.IsReady): return
currBar = self.window[0] # Current bar had index zero.
pastBar = self.window[1] # Past bar has index one.

In the attached backtest, we also show how to use rolling window with indicators and our buy signal is based on a simple moving average. 

1

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.


Hello Alexandre,

thank you very much for your answer. These rolling windows seem to be exactly what I need. For what I have in mind I need data of different resolutions of the same stock though. How to accomplish that? If I've make two rolling windows and use 

        self.AddEquity("SPY", Resolution.Daily)
        self.AddEquity("SPY", Resolution.Second)

in initialilize how to I change self.window.Add(data["SPY"]) if I want one of the resolutions?

Kind regards,

Christian Lauer  

 

0

We cannot subscribe to more than one resolution (and market).
When we want to work with more than one resolution, we need to use consolidators, where we subscribe to higher resolution data and consolidate into lower resolution.
The consolidated bars will arrive at an event handler that we define. There we will add the daily bars in the correspondent rolling window:

# In Initialize
self.AddEquity("SPY", Resolution.Second)

consolidator = TradeBarConsolidator(timedelta(1))
consolidator.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator("SPY", consolidator)

self.daily = RollingWindow[TradeBar](2)
self.window = RollingWindow[TradeBar](2)

# Add daily bar to daily rolling window
def OnDailyData(self, sender, bar):
self.daily.Add(bar)

# Add second bar to window rolling window
def OnData(self, data):
self.window.Add(data["SPY"])

 

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.


 

 

from QuantConnect.Data.Market import TradeBar
from datetime import timedelta

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(2013,10,1) #Set Start Date
self.SetEndDate(2013,11,1) #Set End Date
self.SetCash(100000) #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.AddEquity("SPY", Resolution.Second)

consolidator = TradeBarConsolidator(timedelta(1))
consolidator.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator("SPY", consolidator)

self.daily = RollingWindow[TradeBar](2)
self.window = RollingWindow[TradeBar](2)

# Add daily bar to daily rolling window
def OnDailyData(self, sender, bar):
self.daily.Add(bar)


# Add second bar to window rolling window
def OnData(self, data):
self.window.Add(data["SPY"])
if not (self.window.IsReady and self.daily.IsReady): return
currBar = self.window[0]
yesterdayc = self.daily[1].close
if not self.Portfolio.Invested and currBar<yesterdyc:
self.SetHoldings("SPY", 1)

 

 

Hello Alexandre,

thank you for your quick answer! I've copied the code but I get an error. What have I done wrong?

Error: Object reference not set to an instance of an object Stack Trace

0

Please post the backtest @Christian for help to debug it.

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.


In the code above, the algorithm class is missing. We want the Close of the current bar (currBar = self.window[0].Close) to compare with the close of the previous bar (yesterdayc = self.daily[1].Close).

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.


Thank you for your help again. I've tried to implent a sell signal but I get another strange error now.

from QuantConnect.Data.Market import TradeBar
from datetime import timedelta

class MyAlgorithm(QCAlgorithm):
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(2013,10,1) #Set Start Date
self.SetEndDate(2013,11,1) #Set End Date
self.SetCash(100000) #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.AddEquity("SPY", Resolution.Second)

consolidator = TradeBarConsolidator(timedelta(1))
consolidator.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator("SPY", consolidator)

self.daily = RollingWindow[TradeBar](2)
self.window = RollingWindow[TradeBar](2)

# Add daily bar to daily rolling window
def OnDailyData(self, sender, bar):
self.daily.Add(bar)


# Add second bar to window rolling window
def OnData(self, data):
self.window.Add(data["SPY"])
if not (self.window.IsReady and self.daily.IsReady): return
currBar = self.window[0].Close
yesterdayc = self.daily[1].Close
if not self.Portfolio.Invested and currBar<yesterdayc:
self.SetHoldings("SPY", 1)
if portfolio["SPY"].Price *1.01< Securities["SPY"].Price:
self.SetHoldings("SPY", 0)

14 | 11:31:25:

Algorithm.Initialize() Error: Loader.TryCreatePythonAlgorithm(): Unable to import python module ./cache/algorithm/main.pyc. LoadLibrary Try re-building algorithm. Stack Trace: at QuantConnect.Lean.Engine.Setup.BacktestingSetupHandler.CreateAlgorithmInstance (QuantConnect.Packets.AlgorithmNodePacket algorithmNodePacket, System.String assemblyPath) [0x00061] in <80689db089f84327a006ec7abec7cad3>:0
at QuantConnect.Lean.Engine.Engine.Run (QuantConnect.Packets.AlgorithmNodePacket job, QuantConnect.Lean.Engine.AlgorithmManager manager, System.String assemblyPath) [0x000e0] in <80689db089f84327a006ec7abec7cad3>:0 (Open Stacktrace)

15 | 11:31:25:

Your log was successfully created and can be retrieved from: https://www.quantconnect.com/backtest/35524/646286/d840c2b00121b525baee7121d9dc67db-log.txt

0

Could someone please help me? Even though I have no idea what causes this error, I don't think it should be difficult to fix : )

0

We couldn't reproduce that error, but this line have some issues:

if portfolio["SPY"].Price *1.01< Securities["SPY"].Price:

First, Portfolio and Securities are class attributes, so we need to refer to them with self.: self.Portfolio and self.Securities.
Price in both cases refer to the same value, therefore that expression is always false.
Finally, we cannot multiply decimal.decimal (Price) by float (1.01), We need to convert them:

import decimal as d
factor = d.Decimal(1.01)

 

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.


Hello Alexandre,

thank you for your quick reply. Now I have a problem with comments. I've implented

self.Debug(str(self.Securities["SPY"].Price)","str(currBar))

but I'm told this is ínvalid syntax.

Thank you for your help.

Kind regards,

Christian Lauer

from QuantConnect.Data.Market import TradeBar
from datetime import timedelta
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
import decimal as d

class MyAlgorithm(QCAlgorithm):
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(2013,10,1) #Set Start Date
self.SetEndDate(2013,10,8) #Set End Date
self.SetCash(100000) #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.AddEquity("SPY", Resolution.Second)

consolidator = TradeBarConsolidator(timedelta(1))
consolidator.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator("SPY", consolidator)

self.daily = RollingWindow[TradeBar](2)
self.window = RollingWindow[TradeBar](2)


# Add daily bar to daily rolling window
def OnDailyData(self, sender, bar):
self.daily.Add(bar)


# Add second bar to window rolling window
def OnData(self, data):
self.window.Add(data["SPY"])
factor = d.Decimal(1.01)
if not (self.window.IsReady and self.daily.IsReady): return
currBar = self.window[0].Close
yesterdayc = self.daily[1].Close
if not self.Portfolio.Invested and currBar<yesterdayc:
self.SetHoldings("SPY", 1)
self.Debug(str(self.Securities["SPY"].Price)","str(currBar))
if self.Securities["SPY"].Price *factor< currBar:
self.SetHoldings("SPY", 0)

 

0

# We can use '+' for string concat in python
self.Debug(str(self.Securities["SPY"].Price) + "," + str(currBar))

 

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.


Hello Alexandre,

thank you for your help again. Now there's still the issue that, as you pointed out, I compare the same price. I used self.portfolio["SPY"].price because I thought this would give me the price of the stock in the portfolio for which it was bought. As this is not the case, which attribute is the right one for this?

Kind regards,

Christian Lauer

0

Christian Lauer the Portfolio is a collection of SecurityHolding objects indexed by symbol.

You can see all the security holding properties here:

https://github.com/QuantConnect/Lean/blob/master/Common/Securities/SecurityHolding.cs

I think they are case sensitive so you'll have to use "AveragePrice" -- this is the avg cost of your holdings,

1

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.


Thank you for your answer, Jared.

I have now added another consolidator for minute resolution and scheduled an event for buying. Some backtests work fine now, on others I get an error, though.

Thank you for your help.

Kind regards,

Christian Lauer

Runtime Error: Python.Runtime.PythonException: AttributeError : 'NoneType' object has no attribute 'Close'
at Python.Runtime.PyObject.Invoke (Python.Runtime.PyTuple args, Python.Runtime.PyDict kw) [0x00033] in <14452d8e618b4a588d1da22cca9cdbfe>:0
at Python.Runtime.PyObject.InvokeMethod (System.String name, Python.Runtime.PyTuple args, Python.Runtime.PyDict kw) [0x00007] in <14452d8e618b4a588d1da22cca9cdbfe>:0
at Python.Runtime.PyObject.TryInvokeMember (System.Dynamic.InvokeMemberBinder binder, System.Object[] args, System.Object& result) [0x0003e] in <14452d8e618b4a588d1da22cca9cdbfe>:0
at (wrapper dynamic-method) System.Object:CallSite.Target (System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,object,QuantConnect.Data.Slice)
at QuantConnect.AlgorithmFactory.Python.Wrappers.AlgorithmPythonWrapper.OnData (QuantConnect.Data.Slice slice) [0x000c6] in <c3e0e862262f416c8521641e96d97b9d>:0
at QuantConnect.Lean.Engine.AlgorithmManager.Run (QuantConnect.Packets.AlgorithmNodePacket job, QuantConnect.Interfaces.IAlgorithm algorithm, QuantConnect.Lean.Engine.DataFeeds.IDataFeed feed, QuantConnect.Lean.Engine.TransactionHandlers.ITransactionHandler transactions, QuantConnect.Lean.Engine.Results.IResultHandler results, QuantConnect.Lean.Engine.RealTime.IRealTimeHandler realtime, QuantConnect.Lean.Engine.Server.ILeanManager leanManager, System.Threading.CancellationToken token) [0x012d0] in <bf6d7e74e85a4976b81fd6609e403cea>:0 (Open Stacktrace)

from QuantConnect.Data.Market import TradeBar
from datetime import timedelta
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
import decimal as d

class MyAlgorithm(QCAlgorithm):
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(2013,05,1) #Set Start Date
self.SetEndDate(2013,07,19)
self.SetCash(100000) #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.AddEquity("SPY", Resolution.Second)

consolidator = TradeBarConsolidator(timedelta(1))
consolidator.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator("SPY", consolidator)

consolidatorm = TradeBarConsolidator(60)
consolidatorm.DataConsolidated += self.OnMinuteData
self.SubscriptionManager.AddConsolidator("SPY", consolidatorm)

self.daily = RollingWindow[TradeBar](2)
self.minute = RollingWindow[TradeBar](2)
self.window = RollingWindow[TradeBar](2)

self.Schedule.On(self.DateRules.EveryDay(),
self.TimeRules.At(9, 31),
Action(self.One))




# Add daily bar to daily rolling window
def OnDailyData(self, sender, bar):
self.daily.Add(bar)

def OnMinuteData(self, sender, bar):
self.minute.Add(bar)

def One(self):
if not (self.window.IsReady and self.daily.IsReady and self.minute.IsReady): return
currBar = self.window[0].Close
yesterdayc = self.daily[1].Close
minuteBarC = self.minute[1].Close
minuteBar0 = self.minute[1].Open
self.Debug(str(self.Securities["SPY"].Price) + "," + str(currBar)+str(minuteBar0)+str(minuteBarC))
if not self.Portfolio.Invested and currBar<yesterdayc and minuteBar0<minuteBarC:
self.SetHoldings("SPY", 1)



# Add second bar to window rolling window
def OnData(self, data):
self.window.Add(data["SPY"])
if not (self.window.IsReady): return
self.Debug("haha")
factor = d.Decimal(1.01)
currBar = self.window[0].Close
if self.Portfolio["SPY"].AveragePrice *factor< currBar:
self.SetHoldings("SPY", 0)

 

0

Please add a check for None, in OnData:

def OnData(self, data):
if data["SPY"] is None : return

since you are trying to get the Close from a None that was added in the rolling window.

1

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.


Hello Alexandre,

thank you for your help again. When I run a backtest from May to July 2013, I get an error on one day saying my buying power was insufficient. I thought this was caused maybe because there somehow was an existing order so that I got two orders for a long position. I've added a line to only order if SPY is not in my open orders but I still get that error. What is the problem? 

Kind regards,

Christian Lauer

from QuantConnect.Data.Market import TradeBar
from datetime import timedelta
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
import decimal as d

class MyAlgorithm(QCAlgorithm):
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(2013,05,1) #Set Start Date
self.SetEndDate(2013,07,19)
self.SetCash(100000) #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.AddEquity("SPY", Resolution.Second)

consolidator = TradeBarConsolidator(timedelta(1))
consolidator.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator("SPY", consolidator)

consolidatorm = TradeBarConsolidator(60)
consolidatorm.DataConsolidated += self.OnMinuteData
self.SubscriptionManager.AddConsolidator("SPY", consolidatorm)

self.daily = RollingWindow[TradeBar](2)
self.minute = RollingWindow[TradeBar](2)
self.window = RollingWindow[TradeBar](2)

self.Schedule.On(self.DateRules.EveryDay(),
self.TimeRules.At(9, 31),
Action(self.One))




# Add daily bar to daily rolling window
def OnDailyData(self, sender, bar):
self.daily.Add(bar)

def OnMinuteData(self, sender, bar):
self.minute.Add(bar)

def One(self):
if not (self.window.IsReady and self.daily.IsReady and self.minute.IsReady): return
openOrders = self.Transactions.GetOpenOrders()
currBar = self.window[0].Close
yesterdayc = self.daily[1].Close
minuteBarC = self.minute[1].Close
minuteBar0 = self.minute[1].Open
self.Debug(str(self.Securities["SPY"].Price) + "," + str(currBar)+str(minuteBar0)+str(minuteBarC))
if not self.Portfolio.Invested and currBar<yesterdayc and minuteBar0<minuteBarC and "SPY" not in openOrders:
self.SetHoldings("SPY", 1)



# Add second bar to window rolling window
def OnData(self, data):
if data["SPY"] is None:
return
self.window.Add(data["SPY"])
if not (self.window.IsReady):
return
self.Debug("haha")
factor = d.Decimal(1.01)
currBar = self.window[0].Close
if self.Portfolio["SPY"].AveragePrice *factor< currBar:
self.SetHoldings("SPY", 0)

 

0

Christian Lauer please where possible attach the backtest not a code snippet to make debugging easier.

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.


I'm sorry for the inconvenience. Here's the backtest.

1


I thought if I continued working on the algorithm, I'd maybe find out the problem by myself. But I've got another in addition now. I've implented a sell signal and scheduled a function to close my short positions at the end of each day. But this is done only on the next day after more shares have been shorted. Could someone help me please?

Kind regards,

Christian Lauer

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