Hello All!
I am trying to test 3 crypto currencies (BTCUSD,ETHUSD, and LTCUSD) using EMA of 20 using rolling windows to check old emas.
Initially I added the following:
//initialize moving averages dictionary
for symbol in self.symbols:
self.fast_ema[symbol] = self.EMA(symbol,fast_moving_average,Resolution.Daily)
self.ema_window[symbol] = RollingWindow[float](2)
self.fast_ema[symbol].Updated += lambda sender,updated: self.ema_window[symbol].Add(self.fast_ema[symbol].Current.Value)
What I noticed is that only the last element of the list subcribes to the function. I tried a few combinations, but ended up doing the following which works properly:
self.fast_ema["BTCUSD"] = self.EMA("BTCUSD",fast_moving_average,Resolution.Daily)
self.ema_window["BTCUSD"] = RollingWindow[float](2)
self.fast_ema["BTCUSD"].Updated += lambda sender,updated: self.ema_window["BTCUSD"].Add(self.fast_ema["BTCUSD"].Current.Value)
self.fast_ema["ETHUSD"] = self.EMA("ETHUSD",fast_moving_average,Resolution.Daily)
self.ema_window["ETHUSD"] = RollingWindow[float](2)
self.fast_ema["ETHUSD"].Updated += lambda sender,updated: self.ema_window["ETHUSD"].Add(self.fast_ema["ETHUSD"].Current.Value)
self.fast_ema["LTCUSD"] = self.EMA("LTCUSD",fast_moving_average,Resolution.Daily)
self.ema_window["LTCUSD"] = RollingWindow[float](2)
self.fast_ema["LTCUSD"].Updated += lambda sender,updated: self.ema_window["LTCUSD"].Add(self.fast_ema["LTCUSD"].Current.Value)
Anyone has idea about this behavior. each lambda call should get a new function object reference.
I tried also which named functions leading to the same behavior.
Fred Painchaud
Hi Dario!
My kind of questions!! (my previous life was formal methods)
Short answer:
Use this:
Long answer:
Your lambda is really a “closure”. It has an unbound variable, sumbol, which needs to be bound dynamically. In Python, closures are done syntactically, not dynamically. So, they depend on scopes, syntactical scopes. In your first code, the scope of the lambda is the for loop. Thus, each lambda created has the same scope and thus the same “capture of symbol” ("unbound variable capture" is the term used to say that an unbound variable is dynamically bound in the function and creates a closure). So……… all lambdas end up using the same version of the symbol variable, i.e., the last one (the first lambda first use the first symbol, then on the second iteration, both lambdas point to the second symbol, then, on the third iteration, all 3 point to the third one, etc).
One way to have dynamic capture is to add a param to the lambda and set it to the dynamic variable by default, like this:
The name of the param needs to be the same as the unbound variable. You are then basically cheating as the unbound variable is not unbound anymore so you do not have a closure anymore, there are no unbound variable to capture anymore.
The interface to the event handler is to have two params, not 3 (sender and updated). But the third one that you have has a default value set to the bound variable, so it is not needed, it is fixed dynamically has lambdas are created…
I have not tested this 😊. Just using neurons here - which can lead to surprises…
Fred
Dario Teodori
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!