Hi,
I am new to quant and I am trying to do the basics that are doing a trade with a stop loss and a take profit.
In my algorithm to set the orders I do:
self.marketOrder=self.MarketOrder( self.symbol,-50000)
self.limitOrder=self.LimitOrder(self.symbol,50000,price-0.20)
self.stopOrder=self.StopMarketOrder(self.symbol,50000,price+0.10)
And when the stop or the limit order is filled I cancel the other one to avoid filling both leading to a living trade that should not exist:
def OnOrderEvent(self,orderEvent):
self.Log(orderEvent)
order = self.Transactions.GetOrderById(orderEvent.OrderId)
if self.limitOrder is not None and self.stopOrder is not None and orderEvent.Status==OrderStatus.Filled and (order.Id== self.limitOrder.OrderId or order.Id==self.stopOrder.OrderId):
if order.Id==self.limitOrder.OrderId:
#self.Log("Stop order cancelled: %d" %self.limitOrder.OrderId)
self.stopOrder.Cancel()
else:
#self.Log("limit order cancelled: %d" %self.stopOrder.OrderId)
self.limitOrder.Cancel()
This works for 99% of the trades in the attached backtest.
But it does not work for one. And unless I am missing something obvious, it seems to me that it is a bug.
Indeed, in the log we can see:
2020-03-12 14:00:00 : Warning: To meet brokerage precision requirements, order StopPrice was rounded to 76.706 from 76.7055
2020-03-12 14:00:00 : Time: 03/12/2020 17:10:00 OrderID: 13 EventID: 1 Symbol: CADJPY Status: Submitted Quantity: -50000
2020-03-12 14:00:00 : Time: 03/12/2020 17:10:00 OrderID: 13 EventID: 2 Symbol: CADJPY Status: Filled Quantity: -50000 FillQuantity: -50000 FillPrice: 76.589 JPY
2020-03-12 14:00:00 : Time: 03/12/2020 17:10:00 OrderID: 14 EventID: 1 Symbol: CADJPY Status: Submitted Quantity: 50000 LimitPrice: 76.406
2020-03-12 14:00:00 : Time: 03/12/2020 17:10:00 OrderID: 15 EventID: 1 Symbol: CADJPY Status: Submitted Quantity: 50000 StopPrice: 76.706
2020-03-12 14:00:00 : Time: 03/12/2020 18:00:00 OrderID: 14 EventID: 2 Symbol: CADJPY Status: Filled Quantity: 50000 FillQuantity: 50000 FillPrice: 76.406 JPY LimitPrice: 76.406
2020-03-12 14:00:00 : Time: 03/12/2020 18:00:00 OrderID: 15 EventID: 2 Symbol: CADJPY Status: CancelPending Quantity: 50000 StopPrice: 76.706
2020-03-12 14:00:00 : Time: 03/12/2020 18:00:00 OrderID: 15 EventID: 3 Symbol: CADJPY Status: Filled Quantity: 50000 FillQuantity: 50000 FillPrice: 76.706 JPY StopPrice: 76.706
So the stop loss is filled, then the cancel request is sent and then the limit order is filled instead of being canceled.
There are 30 pipsĀ between the limit and the stop loss so unless the 30 pips are reached in a second at that time in live, this should not happen from my understanding right?
Thank you for any hint of what I am missing or confirming it is a bug.
Regards
Pierre Guilet
I inverse the execution order sorry. The limit is filled, the stop losss cancellation is sent and then is filled
Derek Melchin
Hi Pierre,
This can occur when a single candle crosses both the stop loss and take profit orders. To avoid this issue, consider increasing the resolution of CADJPY from hourly to minute. Since the algorithm makes trading decisions every 10 minutes, it should be subscribed to minute data anyways.
Best,
Derek Melchin
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.
Pierre Guilet
Hi Derek,
Thank you for your answer.
I changed it to minutes and it works.
However it is not obvious. Ideally it should work like if we were in live. I guess that in live the sl or limit is triggered as soon as the level is reached whatever resolution we have right?
So this seems to me a technical limitation in backtesting related to the way order triggering is computed that is based on resolution.
As such I think it should be documented in the backtestingĀ section of the documentation with a reference to it in the market order section. That would have make me avoid this mistake.
Any way thank you again quant is a great tool.
Regards,
Ā
Ā
Pierre Guilet
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!