Hello !
I post my question again, as last time I used “LEAN” tag in my question, and it was moved to the “Lean Issues” category, not to the “Newest”.
So I have recently started my journey with Quantconnect and I am trying to implement my first, simple strategy. Although I managed to complete (hopefully) the majority of work needed, there is a problem with rolling windows which I can't solve,
The strategy should work as follows:
- calculate sum of 2 securities from 2 days ago
- calculate sum of these securities from 1 day ago
- if the sum of the previous day is higher than from 2 days ago, then open specific positions
- if its lower, open positions in opposite directions
The problem is, I don't know how to “attach” rolling window function to specific securities. As you can see in lines 25-31, I tried to collect closing prices, but do not know how to show the function, closing prices of which security I am looking for.
I would really aprreciate any help/tips :)
class CustomIndexStrategy(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 2, 3)
self.SetCash(100000)
self.SetBrokerageModel(BrokerageName.OandaBrokerage)
self.AUDCHF = self.AddForex("AUDCHF", Resolution.Daily, Market.Oanda)
self.USDZAR = self.AddForex("USDZAR", Resolution.Daily, Market.Oanda)
self.SetBenchmark("SPY")
self.rollingWindow = RollingWindow[TradeBar](2) #rolling window indicator to check prices of last 2 days
def OnData(self,data):
#check if rolling window is ready
if not self.rollingWindows.IsReady:
return
# Add new candles to rolling windows
self.rollingWindow.Add(data["AUDCHF"])
self.rollingWindow.Add(data["USDZAR"])
#Get closing prices from 2 days ago
close_2D_AUDCHF = self.rollingWindow [self.rollingWindow.Count-2].Close
close_2D_USDZAR = self.rollingWindow [self.rollingWindow.Count-2].Close
#get closing prices from 1 day ago
cloes_1D_AUDCHF = self.rollingWindow [self.rollingWindow.Count-1].Close
close_1D_USDZAR = self.rollingWindow [self.rollingWindow.Count-1].Close
#sum of closing prices of AUD and USDZAR from 2 days ago
two_day_Sum = close_2D_AUDCHF + close_2D_USDZAR
#sum of closing prices of AUD and USDZAR from 1 day ago
one_day_Sum = cloes_1D_AUDCHF + close_1D_USDZAR
# check if we have any open positions
if self.Portfolio.Invested:
return
#trading rule 1: if sum of closing prices from 1 day ago is lower than from 2 days ago:
if not self.Portfolio.Invested:
if one_day_Sum < two_day_Sum:
self.MarketOrder("USDZAR", -2000,0.95*self.Securities["AUDCHF"].Close)
self.MarketOrder("AUDUSD", 2000,0.95*self.Securities["AUDCHF"].Close)
#trading rule 2: if sum of closing prices from 1 day ago is higher than from 2 days ago:
if one_day_Sum > two_day_Sum:
self.MarketOrder("USDZAR", 2000, 0.95*self.Securities["AUDCHF"].Close)
self.MarketOrder("AUDUSD", -2000, 0.95*self.Securities["AUDCHF"].Close)
pass
Adam W
I would recommend keeping a list of symbol tickers, and a dictionary of separate RollingWindows for each symbol like:
Sebul
Hi Adam,
Thank you very much for your recommendation, the code looks much cleaner indeed !
I applied your suggestions, however the code is still not working. It doesn't even print the “debug” statement from lines 49 and 55. Do you know what could be the reason of it? I think I followed your advices correctly, but did I miss something?
Also, could you please help me in understanding why before and after currency Tickers you typed single apostrophes ' instead of double ‘’ ? I thought that double apostrophes indicate which security we are referring to. I apologise if it is a dumb question but as I mentioned, I have recently started my journey with this environment :)
Adam W
No problem and welcome to QC!
I think it may be that there's some server maintenance going on. (I just tried running a simple buy and hold and that didn't work either, so maybe try again in a few hours).
One thing I noticed is the order logic - the arguments for MarketOrder should be (symbol, quantity, True/False for asychronous orders). Did you mean to do LimitOrder instead? Also since it's forex, you might want to consider using automatic position sizing via `SetHoldings` (e.g. `self.SetHoldings(self.AUDCHF, -0.5)` or manually compute the quantity if the logic here is supposed to represent equal positions in AUDCHF and USDZAR.
The single/double apostrophes in Python just denote a string, and are equivalent. I just prefer the single one because I don't have to press an extra shift 😊
Sebul
I just tried to run a simple strategy and it worked, so I think the maintenance is not the issue in my case…
And thanks for pointing out my mistake in the MarketOrder. I deleted the unnecessary part. I also tried to check if the problem is somehow related to position sizing of Forex securities so I changed everywhere securities in the code from AUDCHF and USDZAR into SPY and QQQ. Unfortunately, still nothing happens..
Any more ideas/suggestions what could be the problem in my code? Seems like everything should work correctly.
Adam W
I ran your code and caught some other minor issues I had missed initially - here's a working version
Sebul
Thank you very much Adam, I really appreciate your help!
I also implemented your suggestions regarding Stop Loss, it all works fine! The only thing I am still struggling with is the concept of setting a SL and TP on a sum of 2 securities. I do understand how to set up limits on single securities, but how can I do this on a value, which is a sum of 2 assets? It should work like this:
I have been trying to find the solution, but don't know which area I should be focusing on. Do you think that maybe a synthetic asset indicator could solve this problem?
Adam W
Hmm well one way to do that would be to:
Take a look at some of the docs/examples, and let me know if you have any questions. This would be good practice for getting familiar with how events and data flows through LEAN as well.
Sebul
Thanks, I will definitely have a look!
In the meantime I wanted to create a very simple rule, which closes a position 3 days after its opening date.
I found a similar question on forum:
However, the response was related to minutes timeframes instead of daily, as in my case. Despite this, I implemented Derek's response into my code, but it does not work.
I guess that the problem is with line 54. I am confused on how to solve it. I adjusted the first part, so self.ticket.Time into days, by adding “ .day " at the end, and by changing minutes into days in the timedelta function.
Unfortunately, the error which I receive is as follows:
Trying to perform a summation, subtraction, multiplication or division between 'int' and 'datetime.timedelta' objects throws a TypeError exception. To prevent the exception, ensure that both values share the same type.
at OnData
elif self.UtcTime >= self.ticket.Time.day + timedelta(days = 3): line 54
By any chance, do you have any idea on how to solve this issue? I know this question is not directly related to the topic of this post, therefore if you think it would be better for me to post this issue by adding a new question on forum, I would be more than happy to do so :)
Nico Xenox
Hey sebul
Didnt look trough the whole Code but the problem might be this:
change it to:
Sebul
Hi Nico,
I tried typing this before, but then I receive this error:
Nico Xenox
Hey @sebul
I think you might need to change a line of code.
This:
To this:
Sebul
Yes it works now, thank you for your help Nico Xenox and Adam W !
Sebul
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!