Hi,
I have been facing a problem trying to access a dictionary to store information when a security is purchased.
The error is:
Error Message
Runtime Error: Trying to retrieve an element from a collection using a key that does not exist in that collection throws a KeyError exception. To prevent the exception, ensure that the key exist in the collection and/or that collection is not empty. at OnData self.Debug(f"Selling {symbol} at {self.Time}, Price: {price}, ARO_DPTL_{self.period}YR: {aro_value}, Purchase discount: {self.cef_discount_purchase[symbol]}") ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^ in main.py: line 80
However, nowhere in my code am I deleting or removing the key related to the Dictionary. But to note, I am using a custom universe that is being filtered and sorted.
Surprisingly though, I am able to log and print the key at the time of purchase, but the key no longer exists at the time of sale:
Snippets of the code attached for reference (modified for confidentiality):
from AlgorithmImports import *
class CustomDataEMFAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2008, 1, 8)
self.set_end_date(2014, 7, 25)
self.set_cash(100000)
self.activeSecurities = set()
universe = self.add_universe(MyCustomUniverseDataClass, "myCustomUniverse", self.selector_function)
self.universe_settings.resolution = Resolution.DAILY
#...
self.discount_purchase = {}
#...
def OnData(self, data):
if self.portfolioTargets == []:
return
for target in self.portfolioTargets:
symbol = target.Symbol
price = self.Securities[symbol].Price # Get the current price
discount_value = self.discount_data[symbol] # Get the discount value from filter
if value < self.lower_limit and not self.Portfolio[symbol].Invested:
self.discount_purchase[symbol] = self.discount_data[symbol]
self.SetHoldings(self.portfolioTargets) # Buy
self.Debug(f"Buying {symbol} at {self.Time}, Price: {price}, Purchase discount: {self.discount_purchase[symbol]}")
elif aro_value > self.upper_limit and self.Portfolio[symbol].Invested:
self.Liquidate(symbol) # Sell
self.Debug(f"Selling {symbol} at {self.Time}, Price: {price}, Purchase discount: {self.discount_purchase[symbol]}")
# Example custom universe data; it is virtually identical to other custom data types.
class MyCustomUniverseDataClass(PythonData):
#...
Mia Alissi
Hi Ahmed,
The error message you're seeing is typically thrown when you're trying to access a key in a dictionary that doesn't exist. In your case, it seems to be happening when you're trying to access
self.discount_purchase[symbol]
in yourOnData
method.One possible reason for this could be that the symbol you're trying to access in
self.discount_purchase
is not present in the dictionary at the time of selling. This could happen if the symbol was not added to the dictionary at the time of buying, or if it was somehow removed from the dictionary between the time of buying and selling.To prevent this error, you can add a check to ensure that the symbol exists in the dictionary before trying to access it. Here's how you can do it:
This will ensure that the KeyError is not thrown, and will also give you a debug message when a symbol is being sold that was not present in the
discount_purchase
dictionary at the time of purchase.If you're still facing issues, it would be helpful to see the complete code or a backtest which reproduces the issue. This would allow us to better understand the problem and provide more specific guidance.
For more information on handling KeyErrors, you can refer to these discussions on the QuantConnect forum: Discussion 12130, Discussion 14244, Discussion 14098, Discussion 7633, Discussion 14787, Discussion 13285, Discussion 14724, Discussion 928, Discussion 13816.
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.
Ahmed Jaber
I need to understand why the error is being thrown, the idea is not to avoid it by preventing the error but rather to know why this behavior is happening? Your solution above does not solve the issue.
Mia Alissi
I understand your concern, Ahmed. The KeyError is thrown when a dictionary is accessed with a key that does not exist in it. In your case, the error is thrown when you're trying to access
self.discount_purchase[symbol]
in yourOnData
method.The reason for this could be that the symbol you're trying to access in
self.discount_purchase
is not present in the dictionary at the time of selling. This could happen if the symbol was not added to the dictionary at the time of buying, or if it was somehow removed from the dictionary between the time of buying and selling.One possible scenario could be that the symbol was not added to the dictionary because the condition
value < self.lower_limit and not self.Portfolio[symbol].Invested
was not met. If this condition is not met, the symbol will not be added to thediscount_purchase
dictionary, but it could still be sold later if the conditionaro_value > self.upper_limit and self.Portfolio[symbol].Invested
is met, leading to a KeyError.Another possible scenario could be that the symbol was removed from the
discount_purchase
dictionary somewhere else in your code that is not shown in the snippets you provided.To debug this issue, you could add more logging to your code to track the state of the
discount_purchase
dictionary and the symbols that are being added and removed from it. This could help you identify where and why the symbol is not in the dictionary at the time of selling.If you're still facing issues, it would be helpful to see the complete code or a backtest which reproduces the issue. This would allow us to better understand the problem and provide more specific guidance.
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.
Ahmed Jaber
Algo attached for reference…your help is much appreciated on this!
Mia Alissi
From the code you've provided, it seems like the KeyError could be occurring due to the way you're handling the
self.cef_purchase_discount
dictionary.In your
OnData
method, you're adding a symbol to theself.cef_purchase_discount
dictionary only when you're buying a security:However, you're trying to access the same symbol from the dictionary when you're selling a security:
The KeyError could occur if a symbol is being sold that was not added to the
self.cef_purchase_discount
dictionary at the time of purchase. This could happen if the condition for buying a security (aro_value < self.aro_dptl_lower_limit and not self.Portfolio[symbol].Invested
) was not met for that symbol.To fix this issue, you could add a check to ensure that the symbol exists in the
self.cef_purchase_discount
dictionary before trying to access it:This will prevent the KeyError from being thrown and will also give you a debug message when a symbol is being sold that was not present in the
self.cef_purchase_discount
dictionary at the time of purchase.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.
Ahmed Jaber
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!