Hi Nicholas,
If I've read your code correctly, I think this is roughly what it will do on any given day once the market order condition is hit:
- Market order submitted (I'm assuming here that the 100 shares order is submitted and not the 101 shares order. Did you really mean to have two different quantities?)
- OnOrderEvent runs for submission of market order (this will return early as fill quantity == 0)
- Market order filled
- OnOrderEvent runs for fill of market order, submitting 1 stop market order and 1 limit order
- OnOrderEvent runs for the submission of the 1 stop market order (this will return early as fill quantity == 0)
- OnOrderEvent runs for the submission of the 1 limit order (this will return early as fill quantity == 0)
- [...] Time passes, assume now we hit the Take Profit price
- Limit order filled for 50 shares
- OnOrderEvent runs for the fill of the limit order. As fill quantity != 0, the function does not return early and instead creates 1 new stop market order and 1 new limit order. The reference price used for these two is the fill price of the limit order.
- OnOrderEvent is run once for each of the submissions of the order, returns each time as fill quantity == 0
- [...] Time passes, and the cycle repeats
Â
At point #9, you have a really weird situation:
- Long 50 shares at the initial price from #3. Let's assume it's $100.
- 1 remaining stop order (from #5) for -100 shares at $95.
- 1 new limit order for -50 shares at $110 * 1.1 = $121.
- 1 new stop order for -100 shares at $110 * 0.95 = $104.5.
Â
What happens if the price now drops below $104.5? You only have 50 shares and you're trying to sell 100 - that's not going to work. What happens if the price goes up to $121? You will hit your limit order and sell the remaining shares, but you'll still have your 2 stop orders alive. I hope this illustrates why the algorithm is not behaving as you expect it to. There are a myriad of ways to solve these issues but you'll have to think about the best way. General tips:
- Be really careful and check what type of order the OnOrderEvent refers to by getting the order by its ID (as you've done already) and then checking its .Type property
- Make sure you cancel any outstanding limit or stop orders when they are no longer needed
- Think carefully about how a -50 share take profit works and ask yourself if you're better off either selling all 100 shares or submitting two take profits for the same amount, one slightly above the other, so that you have a chance to sell off your entire position at some point
- Python doesn't need semicolons, get rid of them
- When submitting algorithms to the forums, save people some time by removing the stuff that isn't crucial to how the algorithm operates (such as logs, comments and non-essential functionality)
Â
Â
Now onto your second question. How do you prevent the algorithm from trading more than once per day? This can be achieved in many different ways - one of the easiest ones is to simply store the date of the last trade somewhere in your code and check the current date against that saved date. If they're identical, then you don't trade.