I'm trying to work through some basics for my first trial algorithm.  Questions:

  • I'm trying to do a simple SPY/TLT basket.  I set up SPY and TLT exactly the same.  SPY works; TLT says it has no data and I should warm it up.  I tried but it's not working.  Why does TLT act differently than SPY, and what am I doing wrong?  Why does an equity symbol require warmup?  How should I handle the warmup requirement?  Code & output below.
  • lean cloud backtest --open gives you a nice backtest report (is that what can be attached to a post here?) and a simple tearsheet.  But local backtests don't produce any report at all, except a couple of log files and JSON files that aren't very human-readable.  I can pick out some stats but I'm not very good at interpreting a JSON equity curve.  I thought maybe lean research <project> might do it, but that just opens a basically-empty notebook, with no connection to your project as far as I can see.  Is there a better way to view local backtest results?


class Test1(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2013, 1, 1)  # Set Start Date
        self.SetEndDate(2021, 1, 1)  # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        self.spy = self.AddEquity("SPY", Resolution.Daily)
        self.tlt = self.AddEquity("TLT", Resolution.Daily)
        self.storeYear = self.Time.year

        self.SetWarmUp(200)  ###  Just picked a random value to try to satisfy the warmup requirement

    def OnData(self, slice):

        if self.IsWarmingUp:  ### Should I use slice.HasData?  Or slice.ContainsKey?  Or ... ??
        if not self.Portfolio.Invested:
            self.SetHoldings("SPY", .5)
            self.SetHoldings("TLT", .5)
            self.Debug(f'Opened position on {self.Time:%Y-%m-%d}:  {self.Portfolio["SPY"].Quantity} SPY, {self.Portfolio["TLT"].Quantity} TLT')

        # Rebalance basket every year
        if self.Time.year != self.storeYear:
            self.storeYear = self.Time.year
            self.SetHoldings("SPY", .5)
            self.SetHoldings("TLT", .5)
            self.Debug(f'Rebalance on {self.Time:%Y-%m-%d}:  {self.Portfolio["SPY"].Quantity} SPY, {self.Portfolio["TLT"].Quantity} TLT')

It doesn't buy any TLT at all, and in fact the initial position doesn't buy SPY either.  ??  Debug output:  (with IsWarmingUp)

2021-06-28T15:45:33.8638945Z TRACE:: Debug: Algorithm finished warming up.
Opened position on 2013-01-01:  0.0 SPY, 0.0 TLT
2021-06-28T15:45:33.8653526Z ERROR:: TLT: The security does not have an accurate price as it has not yet received a bar of data. Before placing a trade (or using SetHoldings) warm up your algorithm with SetWarmup, or use slice.Contains(symbol) to confirm the Slice object has price before using the data. Data does not necessarily all arrive at the same time so your algorithm should confirm the data is ready before using it. In live trading this can mean you do not have an active subscription to the asset class you're trying to trade. If using custom data make sure you've set the 'Value' property.
2021-06-28T15:45:34.0162317Z TRACE:: Debug: Rebalance on 2014-01-01:  410.0 SPY, 0.0 TLT
2021-06-28T15:45:34.1172608Z TRACE:: Debug: Rebalance on 2015-01-01:  358.0 SPY, 0.0 TLT
2021-06-28T15:45:34.2180536Z TRACE:: Debug: Rebalance on 2016-01-01:  337.0 SPY, 0.0 TLT
2021-06-28T15:45:34.3188668Z TRACE:: Debug: Rebalance on 2017-01-04:  335.0 SPY, 0.0 TLT
2021-06-28T15:45:34.4225254Z TRACE:: Debug: Rebalance on 2018-01-03:  316.0 SPY, 0.0 TLT
2021-06-28T15:45:34.5233399Z TRACE:: Debug: Rebalance on 2019-01-01:  288.0 SPY, 0.0 TLT
2021-06-28T15:45:34.6242421Z TRACE:: Debug: Rebalance on 2020-01-01:  295.0 SPY, 0.0 TLT
2021-06-28T15:45:34.6954721Z TRACE:: Synchronizer.GetEnumerator(): Exited thread.

I tried using slice.ContainsKey("TLT") and it didn't get the error, but it didn't enter any trades either …