My algorithm relies heavily on an accurate Historical High (HH) (52-wk-high is fine) to make buy/sell decisions.
Initially I had though that putting the stock in Raw normalization mode would be best. (Then the stock values are historically accurate, and I can trade off the original stock price.)
However, when I reference self.HISTORICAL_HIGH.Current.Value (which I presume re-evaluates the high each new time slice in the sim), it is never adjusting to the new split values after a split event.
As shown below, I have tried adjusting the historical high based on the known split differential but it is just continuing to use the old (pre-split HH) before doing the adjustment - so this doesn't fix it. In the code snippets below self.HISTORICAL_HIGH.Current.Value continues to use the previously-determined HH after the split, and never resets to new HH thresholds when they occur.
I see three potential solutions to this problem:
- There should be a function, or a common adjustment, to the self.MAX() function which auto-adjusts for splits.
- Maybe I add/load each stock ticker twice. Once in Raw, and once in Adjusted, and then use the adjusted one in my HH calculation?
- Maybe I made an error in choosing Raw to begin with. Maybe I should default to adjusted. But if I do that then there are a bunch of downstream negative effects. Example: It's hard to determine if I have enough cash to purchase a stock, because I need to adjust the stock price according to the split differential before doing a buy.
Has anyone dealt with this problem? It seems like it should be a common issue. What is the best solution?
Thanks.
def Initialize(self): # PREPARATORY ITEMS BEFORE SIMULATION
self.CURRENT_STOCK = self.AddEquity(self.STOCK_ONE, Resolution.Daily)
self.CURRENT_STOCK.SetDataNormalizationMode(DataNormalizationMode.Raw) # Do not adjust for splits in the data
self.HISTORICAL_HIGH = self.MAX(self.STOCK_ONE, 253, Resolution.Daily, Field.High) # Get 52-wk-high (non-adjusted, raw)
def OnData(self, data): # PROCESSES REPEATEDLY THROUGHOUT SIMULATION
# Determine if there was a split
if data.Splits.ContainsKey(self.STOCK_ONE):
## Log split information
stockSplit = data.Splits[self.STOCK_ONE]
if stockSplit.Type == 0:
self.Log('Stock will split next trading day')
if stockSplit.Type == 1:
self.SPLIT_DIFF = stockSplit.SplitFactor # Save the new split differential if one occurred
self.Log("Split type: {0}, Split factor: {1}, Reference price: {2}".format(stockSplit.Type, stockSplit.SplitFactor, stockSplit.ReferencePrice))
#HH Calculations
# Problem: .Current.Value DOES NOT adjust for splits
self.ADJ_HISTORICAL_HIGH = self.HISTORICAL_HIGH.Current.Value * self.SPLIT_DIFF # Adjust the HH based on any splits that might have been reported (Q: does this support multiple splits?)
Varad Kabade
Hi Jeffrey Axup,
We recommend using the Adjusted price to get smooth values, and we can reset and warm up the indicator whenever a split/dividend event occurs. We have implemented an example algorithm showing the above. To tackle the issue of buying power, you can calculate the buying quantity manually. We recommend looking at the example algorithm that has implemented the above. Refer to the attached backtest.
Best,
Varad Kabade
Jeffrey Axup
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!