This will hopefully plug the last gap remaining in WL8 live trading capability. WL8 already has some support for syncing your Strategy with the underlying broker account, but Sync Live Positons will prevent some complications like orphan positions.
In a live trading context, streaming chart or strategy monitor, when this option is enabled, prior to running the last bar of data, WL8 will delete all existing theoretical positons, and add the positons from the live broker account.
Pros:
- We shouldn't have any more orphan positons or orphan positons sales.
- If the broker failed to sell a position by not being able to fill a limit price, for example, the position will still be there for WL8 to try and exit again.
Cons:
- It won’t be as easy to auto-trade strategies that maintain multiple positions in the same symbol.
- You’re getting the whole position from the broker, so if you want to exclude a part of it you’ll still have to adjust the position size accordingly.
Vote for the request if you like it!
In a live trading context, streaming chart or strategy monitor, when this option is enabled, prior to running the last bar of data, WL8 will delete all existing theoretical positons, and add the positons from the live broker account.
Pros:
- We shouldn't have any more orphan positons or orphan positons sales.
- If the broker failed to sell a position by not being able to fill a limit price, for example, the position will still be there for WL8 to try and exit again.
Cons:
- It won’t be as easy to auto-trade strategies that maintain multiple positions in the same symbol.
- You’re getting the whole position from the broker, so if you want to exclude a part of it you’ll still have to adjust the position size accordingly.
Vote for the request if you like it!
Rename
If we are going to have Live Position available, then maybe we can calculate the Sell Profit Target based on the actual cost
Absolutely!
I just wanted to voice my whole-hearted support for this feature! In live-trading scenarios, I'm constantly running into situations where an order fails for some crazy reason, and I'm always worried about my strategy getting into some busted state where it's incorrectly holding a position that the Strategy Monitor thought it sold long ago.
Being able to use live positions would certainly provide a lot of peace of mind, and for my use cases, none of the Cons are applicable.
Being able to use live positions would certainly provide a lot of peace of mind, and for my use cases, none of the Cons are applicable.
Agree, I'm going to activate this for development!
Hi Mike, Hi Glitch,
I think a very good point is to say: "Be able to use ...". Maybe it can be implemented as an option in the trading settings so that for the users who need to handle the disadvantages they can trade in the current mode.
Personally, I see it exactly like you Mike. Thank you Glitch for this decision.
I think a very good point is to say: "Be able to use ...". Maybe it can be implemented as an option in the trading settings so that for the users who need to handle the disadvantages they can trade in the current mode.
Personally, I see it exactly like you Mike. Thank you Glitch for this decision.
QUOTE:
when this option is enabled, prior to running the last bar of data, WL8 will delete all existing theoretical positions, and add the positions from the live broker account.
Just make sure WL executes the "Sell leg" of the strategy if there's a hanging orphan position that needs to sell, and the "Buy leg" of the strategy if there's a missed position that should have been bought earlier. If there's a
CODE:statement in the code, the above behavior becomes easy to implement because the Sell and Buy leg are clearly defined. If there isn't such a statement, then the user may need to add a pseudo statement to define which sections of the Execute{} code are for Buy and Sell.
HasOpenPosition(bars, PositionType.Long)
I have some code I can email to the development team for doing this, which I've been using for 5 years successfully. The WL6 version works perfectly because it's possible to sell a position on the "current" bar so the Sell leg of the strategy executes immediately. The WL8 version is more confusing because the Sell leg is executed a bar late since PlaceTrade(...) always executes on the next bar so the position remains orphaned for an extra bar. Let me know if you want the code. It's less than 20 lines long in my code library and is a HasOpenPosition(...) replacement.
The only way I can imagine the solution would be to synchronize a Strategy's LastPosition by symbol with the DataSet and BrokerPositions.
Example:
If the Strategy is executing on the Dow 30 DataSet and you have Positions in AAPL and CSCO (both in Dow 30) and also ADSK, BKR, and BBBY (not in the Dow 30), executing GetPositionsAllSymbols() on bars.Count - 1 needs to return AAPL and CSCO - even if the strategy's state on the last bar wouldn't otherwise have open positions for those symbols.
That could be done by injecting new Positions, if required, on the last bar. But that wouldn't work because many strategies need to know the age of a position.
Consequently, I think the solution would be to ignore the last hypothetical exit, if required, for AAPL and CSCO, and let the strategy logic take over normally. For this to work, the strategy will have needed to create a position at least once for the data loaded, which is a reasonable assumption.
Example:
If the Strategy is executing on the Dow 30 DataSet and you have Positions in AAPL and CSCO (both in Dow 30) and also ADSK, BKR, and BBBY (not in the Dow 30), executing GetPositionsAllSymbols() on bars.Count - 1 needs to return AAPL and CSCO - even if the strategy's state on the last bar wouldn't otherwise have open positions for those symbols.
That could be done by injecting new Positions, if required, on the last bar. But that wouldn't work because many strategies need to know the age of a position.
Consequently, I think the solution would be to ignore the last hypothetical exit, if required, for AAPL and CSCO, and let the strategy logic take over normally. For this to work, the strategy will have needed to create a position at least once for the data loaded, which is a reasonable assumption.
It's not that complicated. All you need to do is redirect the HasOpenPosition() in WL8 (IsLastPositionActive() in WL6 below) to the correct Buy or Sell leg of the strategy. The strategy code will automatically handle the rest, which is the beauty of this solution.
I've included the WL6 solution below--which I've been using for five years--because it's easier to follow since it's possible to create a "sham Buy" on the "current" bar (not bar+1 like is normally done in WL6) so there's a simulated position to sell on the next bar (to remove the orphaned position). In WL8, you can't do that, so the code is more confusing.
I've included the WL6 solution below--which I've been using for five years--because it's easier to follow since it's possible to create a "sham Buy" on the "current" bar (not bar+1 like is normally done in WL6) so there's a simulated position to sell on the next bar (to remove the orphaned position). In WL8, you can't do that, so the code is more confusing.
CODE:
namespace WealthLab.Strategies { public class RSDif_Trend : WealthScript { private ResyncPort posTrack = new ResyncPort(); } protected override void Execute() { posTrack.GetWealthScript(this as WealthScript); ... for (int bar = GetTradingLoopStartBar(20); bar < Bars.Count; bar++) { if (posTrack.IsLastPositionActive(bar)) { //Sell code here } else { //Buy code here } } } } namespace Superticker.Components { public class ResyncPort //Resynchronizes the real portfolio to the WL simulation via Alert management { public string[] PortfolioSymbols { get; private set; } //private List<string> symbolsOwned; //open positions in portfolio internal WealthScript WSObj; public ResyncPort() { string wlDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Fidelity Investments\WealthLabDev\1.0.0.0\Data"); FileInfo SymbolsInputFile = new FileInfo(Path.Combine(wlDataDir, "DataSets", "žž symbols owned.xml")); //Wealth-Lab dataset PortfolioSymbols = ReadXmlDataSet(SymbolsInputFile); //input owned symbols } public void GetWealthScript(WealthScript WSRef) { WSObj = WSRef; //WealthScript object reference } /* public string[] PortfolioSymbols //rtn symbols owned by real portfolio { get { return symbolsOwned.ToArray(); } } */ //Enters Buy code when the real portfolio doesn't own the position even if the simulation does //in order to resynchronize the portfolio with the ownership of the simulation. Likewise, //enters Sell code when the real portfolio owns the postition even if the simulation doesn't //in order to resynchronize the portfolio with the ownership of the simulation. public bool IsLastPositionActive(int bar) { if (bar < WSObj.Bars.Count - 1) //Is this the last bar on the Chart where an Alert maybe generated? return WSObj.IsLastPositionActive; //no, so precede normally else //for processing the last bar on the Chart, which may generate an Alert for the off-the-chart bar //return symbolsOwned.Contains(WSObj.Bars.Symbol); //flag Alerts based on real portfolio ownership { if (WSObj.IsLastPositionActive) //Is the simulation executing its Sell code? return Array.IndexOf(PortfolioSymbols, WSObj.Bars.Symbol) != -1; //yes, so exec Sell code *if* actually owned //return symbolsOwned.Contains(WSObj.Bars.Symbol); //yes, so exec Sell code *if* actually owned else { //no, sumulation is executing its Buy code instead if (Array.IndexOf(PortfolioSymbols, WSObj.Bars.Symbol) != -1) //... so does the portfolio actually owned this symbol? //if (symbolsOwned.Contains(WSObj.Bars.Symbol)) //... so does the portfolio actually owned this symbol? { WSObj.SetPaneBackgroundColor(WSObj.PricePane, bar, Color.Plum); WSObj.BuyAtMarket(bar, "Pseudo buy"); //yes, so create a sham Buy so there's a simulated position to sell return true; //exec Sell code to generate an Alert to close this orphaned portfolio position } else return false; //nothing active and Open, so exec Buy code unconditionally } } } } }
QUOTE:I'm pretty sure this will not be the solution for precisely the reason I mentioned that injecting a position "wouldn't work" [for many strategies] because you don't know the age of the position.
//yes, so create a sham Buy so there's a simulated position to sell
I already implied it is "a solution", but it's certainly not the best - imho. But you and I can jawbone all we want. Glitch will probably come up with something that no one has predicted yet, as he often does.
QUOTE:
I'm pretty sure this will not be the solution for precisely the reason I mentioned that injecting a position "wouldn't work" [for many strategies] because you don't know the age of the position.
I'm saying the age of the position should not matter for synchronizing the portfolio with the simulated strategy. In many cases, I intentionally skip buying a position WL wants to buy only to buy it several bars later. This is a good feature of this approach, not a disadvantage. And I would like to preserve this option. (Perhaps this should be a preference option.)
Moreover, if timing which bar needs to be the entry (and for some short-term strategies it is), then the user should be using a crossover test to get precisely in on that bar. I use inequalities instead of crossovers for entry tests because I'm looking for a particular condition to be satisfied.
Just because it doesn't matter for you, it does matter for many non-superticker strategies. Here are 2 concrete examples -
1. Let's say I want sell at a some limit price after having held the position for 10 bars. Futhermore, the limit price depends on the number of bars the position was active. Imagine after 12 bars the limit price hits, but my account didn't exit. If you inject your "sham buy", the strategy won't know place a limit order because the position's age is either wrong or best case, a very good guess.
2. A good number of strategies have profit targets and stop losses. Assuming you can get the basis price of the position from the broker, you'd be covered, but we can't depend on that. We may need to know the signal bar or some other position property that you can't get with a sham buy.
In both of these cases, if you assume that the position belongs to the last hypothetical entry, and you ignored the hypothetical exit (because the real exit didn't occur) the strategy will be in synch and can generate the proper signals.
Is there something about your sham position solution that can solve either one of these cases?
1. Let's say I want sell at a some limit price after having held the position for 10 bars. Futhermore, the limit price depends on the number of bars the position was active. Imagine after 12 bars the limit price hits, but my account didn't exit. If you inject your "sham buy", the strategy won't know place a limit order because the position's age is either wrong or best case, a very good guess.
2. A good number of strategies have profit targets and stop losses. Assuming you can get the basis price of the position from the broker, you'd be covered, but we can't depend on that. We may need to know the signal bar or some other position property that you can't get with a sham buy.
In both of these cases, if you assume that the position belongs to the last hypothetical entry, and you ignored the hypothetical exit (because the real exit didn't occur) the strategy will be in synch and can generate the proper signals.
Is there something about your sham position solution that can solve either one of these cases?
If there is no hypothetical position but one exists in the broker account, a new position will get injected.
If a hypothetical position exists but it does not exist in the broker account, the hypothetical position will get deleted.
If there is a match, then the hypothetical position can get adjusted.
There will never be a perfect solution, that's why this is an OPTION and will have drawbacks, especially for Strategies that rely on the age of the position, because that information will be lost in the first case.
If a hypothetical position exists but it does not exist in the broker account, the hypothetical position will get deleted.
If there is a match, then the hypothetical position can get adjusted.
There will never be a perfect solution, that's why this is an OPTION and will have drawbacks, especially for Strategies that rely on the age of the position, because that information will be lost in the first case.
QUOTE:
If you inject your "sham buy", the strategy won't know place a limit order because the position's age is either wrong or best case, a very good guess.
The "sham buy" is placed unconditionally in the library code whenever an orphan position exists that should have exited. Oh, I see your point; the sham buy isn't carrying the same entry properties as the original entry position.
My main concern is some strategies are designed for very short-term positions, so timing on the bar becomes an issue and needs to be detected with a crossover test. It's these short-term strategies with crossover entries and exits that concerns me. The crossover conditions may fight the handling of out-of-sync cases by the strategy itself. Perhaps there needs to be "overriding behavior" involved, but then this feature needs to be disabled if necessary. Perhaps the solution for short-term strategies needs to be different for long-term strategies, although that complexity doesn't appeal to me so much.
Let me make this statement. I would like a solution that can Buy (or Sell) late if the opportunity to do so favors it. How you do that is up to you.
QUOTE:yes, but not just age - profit target, stop loss, and probably a few others cases.
especially for Strategies that rely on the age of the position, because that information will be lost in the first case.
How about a compromise?
Inject the position with the entry bar details of the last hypothetical entry.
That's what I meant here:
>>If there is a match, then the hypothetical position can get adjusted.<<
>>If there is a match, then the hypothetical position can get adjusted.<<
I like the planned solution. On the preference to enable this feature, a warning might be included saying this feature is not recommended with strategies that depend on time held by the position or crossover entry and exit conditions where a "specific bar" is targeted.
I would keep it simple for version 1.0 of this feature until some feedback is given. Simple is beautiful even if doesn't handle every case.
I would keep it simple for version 1.0 of this feature until some feedback is given. Simple is beautiful even if doesn't handle every case.
Is it possible we might see an initial version of this feature in the next WL8 release or two? Or is it likely still a ways off? I'm really excited to give it a try.
It’s already developed and is now in testing for build 28.
Your Response
Post
Edit Post
Login is required