Hello,
I am trying to code the following exit rules and am running in to the "cannont split a position that is already closed" error. I have searched for insights and examples but haven't come across one that helps.
My exit logic is:
After opening a position, place an initial trailing stop at the entry price minus 1 standard deviation. If the price moves one standard deviation in your favor, I want to split the position and sell half there. The second half should trail by 0.5 StDev. If there is still are positions open at the end of the day, sell at the close.
CODE:
Please log in to see this code.
Not sure what I am doing wrong. One interesting observation is that it seems to break on the bar wherein the split is supposed to happen (but doesn't) and it ends up stopping out on the same bar. Doesn't happen a lot but enough to cause it to throw the error above. Thanks for the help!
Size:
Color:
First thing to correct:
CODE:
Please log in to see this code.
It's hard to see everything that's happening without all of the code, but SplitPosition creates a new Position, which is then the "LastPosition", but you're selling it (variable
s) in the limit order. On the next iteration of the loop, LastPosition that you now assign to
p may already be closed.
After the split, try selling the penultimate position, p, instead:
CODE:
Please log in to see this code.
That said, you're going to have another problem if the Limit order does not execute - the position will keep splitting and splitting. This is one of those cases in which it's "legal" to peek to make sure the limit order will execute. If it won't, then you should not split the position. Here's a shot at that:
CODE:
Please log in to see this code.
Size:
Color:
Thanks Cone. I actually had it that SellAtLimit using p, but then changed it just before I pasted.
I made your changes and am still getting the same error. What is interesting is that some position don't close out the remaining 50 shares and leave them open from 2009.
Here is the full code
CODE:
Please log in to see this code.
Size:
Color:
By the way, BuyAtStop also suffers from peeking into the future:
CODE:
Please log in to see this code.
You can not peek at the bar's Close and then execute a Stop order back in time on that same bar. That should be corrected as
BuyAtStop(bar+1... to avoid the problem.
Next, you declare the
canSplit variable but never check it. I think it originates from this design pattern where it worked:
WealthScript Techniques | Splitting a Position into TwoMy suggestion is to replicate what works as close as possible, w/o breaking something (including the
"if( ActivePositions.Count > 0 )... else" block).
Size:
Color:
Thanks Eugene. I have tried this about three different ways, I think in part because each of the documentation I have found has done it differently - Programming Guide, QuickRef, web.
While I rework my code, two questions for you: for multiposition systems, does the Buy logic go first or last? And for Limit Orders (at a profit target for example), I had assumed that when it hits the price you want it should get out right then, not wait for the next bar where the price could be different. Does WL handle it that way or does it just give you that limit price when you get to the next bar and the entry/exit fires?
Size:
Color:
I reworked it and -think- I have it working. Interestingly (to me anyway), I had been trying to follow the standard exit logic (end of day first, etc.), and in doing so, I was not getting the splitting. Thinking about it, since the splitting is based on a valid peeking scenario, I moved to the beginning of the exit logic and it seemed to work. If I am missing something, please let me know. Thanks!
CODE:
Please log in to see this code.
Size:
Color:
Why did you add the canSplit variable? It will always be the opposite of hasSplit.
If you plan on trading this in real time, you need to add the 'else' snippet that I marked: // last bar of chart; split the position for the alert . Otherwise, the alert to sell half the position at the limit price will never occur, and therefore the code won't match the live trading.
Size:
Color:
Thanks Cone, I appreciate the help. I am not sure I understand why that addition code needs to be included - it looks like it does the same thing as the previous line, so what does that else argument address?
At this point, I am just backtesting.
Size:
Color:
You won't see a difference in backtesting.
This statement:
if (bar < Bars.Count - 1 && High[bar + 1] >= limitprice)
.. checks that the current bar is not the last bar of the chart, which allows you to peek ahead to the high of the next bar to see if the limit price will be hit. This is done so that you do not split the position in code many times over. You only want to split if you know if half the position can be sold.
In live trading, however, you need to create an alert when processing the last bar to sell half the position. (Note, you need to use my construction of the statement block.) The Alert goes to the Orders tool and you enter the limit order with the broker. You obviously don't know if the limit will be hit, but that doesn't matter. I can see how the logic can be confusing, but you just have to think through it for each bar, and what happens when a new bar is added to the chart.
There is another way... you could split the position immediately and create logic to work with both positions. For the backtest, it would mean always paying an extra commission at the end of the day if the limit price is reached because you have to exit two positions. In live trading, however, you could compensate and send only 1 order for the full position.
Anyway, I suggest you use the logic from my post. You won't see a difference in backtesting, but you will when trading live... try it using Paper Trading first! (But be mindful of the limit/stop order limitations of the paper trader .. see User Guide, Orders > Paper Trading > How Orders are Filled.
Size:
Color: