Screenshot is an example of a strategy, which worked today. It was started before the market open. There were no real trades or orders on it, although I later ran the backtest with same settings and there was a trade today.
Rename
Did you select Streaming Bars or Streaming in the Strategy Monitor settings?
If you used Streaming, differences can be expected. See Help > Interactive Brokers.
If you used Streaming, differences can be expected. See Help > Interactive Brokers.
No, it's poling on 15min with pre/post market filter. I noticed that there were no trades on this strategy at all which is kind of weird
Assuming the strategy parameters were the same... the log could help determine what happened, but possibly there was a missed bar or something of the sort. It [almost] always comes down to data. I'd definitely recommend using Streaming Bars so that you get the correct data in a timely fashion.
---
You're using an unlinked DataSet. That allows for data variability based on the order of the Historical Data Providers you have selected... unless IB is your only intraday source, then this argument would fall flat.
---
You're using an unlinked DataSet. That allows for data variability based on the order of the Historical Data Providers you have selected... unless IB is your only intraday source, then this argument would fall flat.
Also on another strategy, which is on 60m forex noticed incorrect work. According to Markets and Symbols today it has to work 24h, however next run in strategy monitor is only next morning at 08.00. For more, some stop orders that are issued by the strategy are displayed with the status error:
However, the broker has these orders as active.
QUOTE:
Quantity adjusted to Sync with size of Position
Order Event Warning:Attribute 'Outside Regular Trading Hours' is ignored based on the order type and destination. PlaceOrder is now being processed.
However, the broker has these orders as active.
At the bottom of the Strategy Monitor Settings dialog, make sure you select the correct market for what you're trading... it needs to be "Currencies".
Re: For more, some stop orders that are issued by the strategy are displayed with the status error
>> Probably you need to use Stop Limit orders. If that's not it, let me know the details (symbols, order type, etc.) that generates the error and I'll look into it.
Edit - that's just a warning, but we can probably clean that up for the next build when trading Currencies.
Re: For more, some stop orders that are issued by the strategy are displayed with the status error
>> Probably you need to use Stop Limit orders. If that's not it, let me know the details (symbols, order type, etc.) that generates the error and I'll look into it.
Edit - that's just a warning, but we can probably clean that up for the next build when trading Currencies.
It's the first thing I've checked, it's Currencies there.
Okay, we'll look into it. While testing something else, I noticed that order blocks were defaulting to the U.S. Market hours even when trading symbols in different markets, so we're already working on that.
QUOTE:I couldn't duplicate that. Last Run and Next Run are displayed in your machine's local time. My machine is in EST, it's currently 2:44AM EST the next Run for a "Currencies" strategy is 3:00AM.
next run in strategy monitor is only next morning at 08.00
What time zone are you in? Would that explain it?
GMT +2.
QUOTE:That's from the strategy monitor log. Even if it's because of the timezone, from Thursday to Friday the strategy must work 24 hours a day.
03/02/2023 02:13:21: Status = LoadingData
03/02/2023 02:13:21: Start Polling Thread
03/02/2023 02:13:21: Populating Data
03/02/2023 02:13:21: Calling GetHistories Pass 1
03/02/2023 02:13:24: GetHistories returned with 9 symbols
...
03/02/2023 02:13:28: NextRun set to 03/02/2023 08:00
03/02/2023 02:13:28: Status = Idle
03/02/2023 08:00:00: Status = Processing
03/02/2023 08:00:00: Pass 1 - Requesting updates for 9 symbols...
03/02/2023 08:00:06: Pass 1 - UpdateHistories returned 9 symbols
03/02/2023 08:00:12: NextRun set to 03/02/2023 09:00
03/02/2023 08:00:12: Status = Completed
03/02/2023 08:00:12: Processed all Symbols
03/02/2023 09:00:00: Status = Processing
I know you said you checked, but please double check it. If the market is Currencies, I can't explain how the next run could have been scheduled for 0800.
I'll check again on other days.
I have rechecked today. If currencies are there the next run for today is set to 17:15, when I put CME for example it adjusts for the next hour
Next Run is set to 17:`15 for 60 minute bars? That can't be right.
Even though I can't duplicate this issue with the Currencies market selected, I believe you, but we need a way to duplicate it to solve it.
-- Edit --
Okay 17:15 is when the market opens on Sunday. Is your computer clock off by 1 day?
Even though I can't duplicate this issue with the Currencies market selected, I believe you, but we need a way to duplicate it to solve it.
-- Edit --
Okay 17:15 is when the market opens on Sunday. Is your computer clock off by 1 day?
Switched back from CME to Currencies and took this screenshot
Given that result and seeing the date as dd/mm/yyyy (per you locale) makes me suspect we're not treating that date properly, so we'll look into that.
Still no trades on a live account, although if I run backtest they are there. It's already on two strategies i tested, the last one was on stocks, i.e. it's not forex specific.
Upd: I've changed Crypto to CME and now it's placing the trades. Waiting the fix to change to Currencies as it should be
Sorry we didn't have it nailed down for buld 25, but it's fixed for the next IB update - build 26. The IB Broker Provider wasn't able to return the correct market because it hadn't implemented the GetMarketFromSymbol(), so it defaulted to U.S. Stocks.
I'm writing in this thread because the picture was saved here, although there is something else now. I found some strategies using Generic evolver, adjusted, tested and saved. All of them showed decent profits. Today I'm testing them all and on the same data and settings they all drain at -30% yearly. My last post and this picture is the same strategy - completely different signals.
Also another same strange thing is that the inclusion of the filter pre/post market affects the result, although in the case of forex, surely should not.
Also another same strange thing is that the inclusion of the filter pre/post market affects the result, although in the case of forex, surely should not.
Would you be able to share one of the strategies? It’s impossible to guess what’s happening without more information.
Also are you sure the symbols are assigned to the Currencies market and not stocks?
Also are you sure the symbols are assigned to the Currencies market and not stocks?
It's one of those few strategies. Not the one from screenshot.
>Also are you sure the symbols are assigned to the Currencies market and not stocks?
I don't see an option to indicate the market in datasets or backtest window. If that setting is in the main window at the bottom, I changed it.
CODE:
<?xml version="1.0" encoding="utf-8"?><Strategy xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance" target="_blank">http://www.w3.org/2001/XMLSchema-instance</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema" target="_blank">http://www.w3.org/2001/XMLSchema</a>"><PreferredValues /><Name>Forex 3 60</Name><Description>Enter a description for the Strategy here.</Description><Author>ww5</Author><CreationDate>2023-02-03T09:42:11.6390728</CreationDate><StrategyType>BuildingBlock</StrategyType><StrategyData>2|V24|True1|31733|1|412|ShortAtClose7|2|V31|05|False4|True1|21|C858|1|426|IndicatorCrossesSignalLine802|2|V31|32|149|Indicator2|117|PivotR1105|2|V31|12|146|Source1|55|False10|-9999999999|9999999991|10|5|False10|BarHistory0|4|True5|False4|NULL4|NULL5|False10|-9999999999|9999999991|10|5|False9|Indicator0|4|True5|False4|NULL4|NULL2|147|Crosses2|101|24|Over5|Under5|Under5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL2|148|Smoother2|1215|McGinleyDynamic332|2|V31|32|146|Source2|1311|<indicator>5|False10|-9999999999|9999999991|10|5|False10|TimeSeries0|4|True5|False4|NULL4|NULL2|146|Period1|01|35|False10|-9999999999|9999999991|10|5|False5|Int320|4|True5|False4|NULL4|NULL2|1422|Simplified calculation1|34|True5|False10|-9999999999|9999999991|10|5|False7|Boolean0|4|True5|False4|NULL4|NULL5|False10|-9999999999|9999999991|10|5|False8|Smoother0|4|True5|False4|NULL4|NULL5|False4|True5|False1|C818|1|425|IndicatorCompareIndicator763|2|V31|42|149|Indicator2|114|High7|2|V31|05|False10|-9999999999|9999999991|10|5|False9|Indicator0|4|True5|False4|NULL4|NULL2|142|is2|101|69|less than21|less than or equal to8|equal to12|not equal to24|greater than or equal to12|greater than12|greater than5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL2|149|Indicator2|1119|ProjectionBandLower201|2|V31|22|146|Source1|55|False10|-9999999999|9999999991|10|5|False10|BarHistory0|4|True5|False4|NULL4|NULL2|146|Period1|02|125|False10|-9999999999|9999999991|10|5|False5|Int320|4|True5|False4|NULL4|NULL5|False10|-9999999999|9999999991|10|5|False9|Indicator0|4|True5|False4|NULL4|NULL2|1417|How many Bars ago1|01|25|False1|09|9999999991|10|5|False5|Int320|4|True5|False4|NULL4|NULL5|False4|True5|False1147|1|416|CoverAtLimitStop486|2|V31|42|1410|Order Type2|101|25|Limit4|Stop5|Limit5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL2|1410|Percentage1|14|3.254|True3|2.53|3.54|0.0510|Percentage5|False6|Double0|4|True5|False4|NULL4|NULL2|1411|Above/Below2|101|25|Above5|Below5|Above5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL2|149|Indicator2|115|Close7|2|V31|05|False10|-9999999999|9999999991|10|5|False9|Indicator0|4|True5|False4|NULL4|NULL5|False4|True1|11|C612|1|425|IndicatorCrossesIndicator557|2|V31|32|149|Indicator2|113|Low7|2|V31|05|False10|-9999999999|9999999991|10|5|False9|Indicator0|4|True5|False4|NULL4|NULL2|147|Crosses2|101|24|Over5|Under4|Over5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL2|149|Indicator2|113|RMF203|2|V31|22|146|Source1|41|35|False10|-9999999999|9999999991|10|5|False10|TimeSeries0|4|True5|False4|NULL4|NULL2|146|Period1|01|55|False10|-9999999999|9999999991|10|5|False5|Int320|4|True5|False4|NULL4|NULL5|False10|-9999999999|9999999991|10|5|False9|Indicator0|4|True5|False4|NULL4|NULL5|False4|True5|False518|1|415|CoverAtStopLoss477|2|V31|42|149|Stop Loss1|13|0.44|True4|0.083|0.44|0.029|Stop Loss5|False6|Double0|4|True5|False4|NULL4|NULL2|1414|Stop Loss Type2|101|27|Percent5|Point7|Percent5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL2|148|Trailing1|35|False5|False10|-9999999999|9999999991|10|5|False7|Boolean0|4|True5|False4|NULL4|NULL2|1414|Trailing Basis2|101|23|Low5|Close3|Low5|False10|-9999999999|9999999991|10|5|False12|StringChoice0|4|True5|False4|NULL4|NULL5|False4|True1|0</StrategyData><LibraryName /><FolderName>Mined</FolderName><DataSetName>Forex IB;Interactive Brokers</DataSetName><UseSelectedDataSetOnly>false</UseSelectedDataSetOnly><SingleSymbolMode>false</SingleSymbolMode><Scale><Frequency>Minute</Frequency><Interval>60</Interval><FilterPrePost>false</FilterPrePost></Scale><DataRange><DataRangeType>DateRange</DataRangeType><RecentValue>10</RecentValue><StartDate>2020-01-01T00:00:00</StartDate><EndDate>2023-01-31T23:59:59</EndDate></DataRange><PositionSize><PositionSizeType>Dollar</PositionSizeType><Amount>500000</Amount><PositionSizerName /><PositionSizerParameters /><StartingCapital>100000</StartingCapital><MarginFactor>10</MarginFactor><MaxOpenPositions>0</MaxOpenPositions><MaxOpenPositionsLong>0</MaxOpenPositionsLong><MaxOpenPositionsShort>0</MaxOpenPositionsShort><MaxOpenPositionsInSymbol>1</MaxOpenPositionsInSymbol><UseNextBarOpenAsBasisPrice>false</UseNextBarOpenAsBasisPrice><StartingCapOptValues><MinValue>50000</MinValue><MaxValue>200000</MaxValue><StepValue>10000</StepValue></StartingCapOptValues><FixedAmountOptValues><MinValue>1000</MinValue><MaxValue>10000</MaxValue><StepValue>1000</StepValue></FixedAmountOptValues><PctEquityOptValues><MinValue>1</MinValue><MaxValue>20</MaxValue><StepValue>1</StepValue></PctEquityOptValues><FixedQtyOptValues><MinValue>100</MinValue><MaxValue>1000</MaxValue><StepValue>100</StepValue></FixedQtyOptValues><MarginOptValues><MinValue>1</MinValue><MaxValue>2</MaxValue><StepValue>0.1</StepValue></MarginOptValues><MaxRiskOptValues><MinValue>5</MinValue><MaxValue>50</MaxValue><StepValue>5</StepValue></MaxRiskOptValues><MaxOpenPosOptValues><MinValue>1</MinValue><MaxValue>1000</MaxValue><StepValue>1</StepValue></MaxOpenPosOptValues><MaxSignalsPerBar>0</MaxSignalsPerBar><StartingCapOpt>false</StartingCapOpt><AmountOpt>false</AmountOpt><MarginOpt>false</MarginOpt><MaxOpenPosOpt>false</MaxOpenPosOpt></PositionSize><Benchmark>SPY</Benchmark><SingleSymbol>SPY</SingleSymbol><RunWithWFOParameters>false</RunWithWFOParameters><RunWithPreferredValues>false</RunWithPreferredValues><RetainNSF>true</RetainNSF><GranularLimitStopScale><Frequency>Daily</Frequency><Interval>1</Interval><FilterPrePost>true</FilterPrePost></GranularLimitStopScale><UpdateGranularData>true</UpdateGranularData><IsWLComPublishedStrategy>false</IsWLComPublishedStrategy><IsWLComUserStrategy>false</IsWLComUserStrategy><MarkedReadOnly>false</MarkedReadOnly><IsRunningInEvolver>false</IsRunningInEvolver><CouldOptimize>true</CouldOptimize><IsLinkedToExternalFile>false</IsLinkedToExternalFile><LinkedFileName /><CompiledStrategyTypeName /></Strategy>
>Also are you sure the symbols are assigned to the Currencies market and not stocks?
I don't see an option to indicate the market in datasets or backtest window. If that setting is in the main window at the bottom, I changed it.
OK so these are coming from IB, so the Currencies market I'm assuming should be set. Let's see what Cone things, he's our resident IB expert here.
The question is, "are you using IB Provider Provider Build 26"? It fixed the issue when WealthLab queries the market from the Broker Provider instead of the Historical Provider.
Maybe we've already been through this above, but backtests are expected to be different if you have NSF Positions and are not assigning Transaction.Weight. What's the NSF Count in the Metrics report?
Maybe we've already been through this above, but backtests are expected to be different if you have NSF Positions and are not assigning Transaction.Weight. What's the NSF Count in the Metrics report?
I have checked both on IB 26 and previous build. No difference. There are no NSF Positions.
Maybe it's some kind of over-optimization. Maybe some kind of indicator calculation, since they all use pivot. May be data related since I get the following situations.
As for this screenshot, the other strategy for example is trading all months from the beginning of 2020 to 01.23
And I've tried to delete the data. In data manager, chose a timeframe, selected all and clicked truncate. The rows with the data are gone, but when I reenter at this dataset they're still there.
Maybe it's some kind of over-optimization. Maybe some kind of indicator calculation, since they all use pivot. May be data related since I get the following situations.
As for this screenshot, the other strategy for example is trading all months from the beginning of 2020 to 01.23
And I've tried to delete the data. In data manager, chose a timeframe, selected all and clicked truncate. The rows with the data are gone, but when I reenter at this dataset they're still there.
What position sizing are you using? You lost 50% of your funds in 2020.
Cone, right, that was the position sizing problem. I was confused by the fact that then there were more rare trades for year 21 and 22. Even if set aside these strategies and don't dig any further, the only thing that remains it's that bar hisotry data is undeletable.
QUOTE:
Maybe some kind of indicator calculation, since they all use pivot:
The pivot indicater used to peek into the future. Please double check if you use the corrected version.
>The pivot indicater used to peek into the future
If this was fixed in one of the previous versions, it explains everything, even more so that the strategies were overly profitable
If this was fixed in one of the previous versions, it explains everything, even more so that the strategies were overly profitable
Here is my backtest
Here is my actual result for IB paper account
I use 0.05% risk. IB paper account is set to 100k, so the backtest. I can still understand that the transactions are different, since it is a paper account and perhaps due to quotes and execution, but money management is radically different. I enter stop and buy limit orders, so I don't see how there can be such a difference. You can also notice that orders sent to the broker have a different amount than positions in the backtest
Here is my actual result for IB paper account
I use 0.05% risk. IB paper account is set to 100k, so the backtest. I can still understand that the transactions are different, since it is a paper account and perhaps due to quotes and execution, but money management is radically different. I enter stop and buy limit orders, so I don't see how there can be such a difference. You can also notice that orders sent to the broker have a different amount than positions in the backtest
Not enough information.
I can't hardly find a trade to compare in those images. PODD appears 7 times in the lower image, but not once on top. There are no time references on the bottom. How is one expected to compare these from our viewpoint?
What are your Trading Preferences?
When did your backtest start?
From the previous discussion, it sounds like the strategy could matter too.
Instead of trying to troubleshoot dozens of trades simultaneously, let's look at ONE and find out why that ONE is different. There will be a reason.
I can't hardly find a trade to compare in those images. PODD appears 7 times in the lower image, but not once on top. There are no time references on the bottom. How is one expected to compare these from our viewpoint?
What are your Trading Preferences?
When did your backtest start?
From the previous discussion, it sounds like the strategy could matter too.
Instead of trying to troubleshoot dozens of trades simultaneously, let's look at ONE and find out why that ONE is different. There will be a reason.
QUOTE:
Instead of trying to troubleshoot dozens of trades simultaneously, let's look at ONE and find out why that ONE is different. There will be a reason.
Today I did just that. Some transactions match, some don't
This is very hard to make sense of. What windows are you even showing, it looks like Accounts and a backtest Positions?
What exactly do you think is incorrect here?
What exactly do you think is incorrect here?
The upper left is Accounts, to the right of it is the Backtest.
The window below is the orders sent filtered by F. Order window to show that they are not partially filled, but completely.
Quantity does not match. All accounts including backtest have ~100k. Max risk 0.05% is used, so the quantity must match. If we compare F, then the quantity matched only in alpaca, but did not match on IB, and even more on Dummy Account. ADI also does not match between backtest and IB. So is Dummy Account.
The window below is the orders sent filtered by F. Order window to show that they are not partially filled, but completely.
Quantity does not match. All accounts including backtest have ~100k. Max risk 0.05% is used, so the quantity must match. If we compare F, then the quantity matched only in alpaca, but did not match on IB, and even more on Dummy Account. ADI also does not match between backtest and IB. So is Dummy Account.
I don't know your full history of trading. Just because you're showing a backtest report, it doesn't mean it "must match" what is shown in accounts. It's the result of backtesting only one system. Your accounts, especially the Dummy Broker, could have already had any number of shares in any number of symbols.
If you want to prove something is wrong here we need to see a specific case of an order that gets filled with a different number of shares at the broker side than what WL submitted. In my experience this just has never occurred.
If you want to prove something is wrong here we need to see a specific case of an order that gets filled with a different number of shares at the broker side than what WL submitted. In my experience this just has never occurred.
I realize it looks like I'm clinging, but I'm really catching bugs. Everything above is the MaxRisk situation, I switched to % of equity so it doesn't bother me anymore. But today I caught an extremely critical bug. Let me tell you right away, paper account was reset before market open, so no open positions. The same with dummy account.
First an example of how it works on a dummy account - everything is correct.
Then how it was on IB:
What led to this situation
The original short order turned into a long position on the bottom line.
So did some other positions that didn't close even though there was a signal.
My settings are as follows
PS: Also it is not very clear to me, here on the first screenshot you can see Order Price 953.16 (Limit 952.72). How can this be if the order is sent as PlaceTrade(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 1, "Short At StopLimit"); ? In such a case, the price of the limit and stop should coincide. On backtest and dummy it's 952.72 and in IB it turns out different.
First an example of how it works on a dummy account - everything is correct.
Then how it was on IB:
What led to this situation
The original short order turned into a long position on the bottom line.
So did some other positions that didn't close even though there was a signal.
My settings are as follows
PS: Also it is not very clear to me, here on the first screenshot you can see Order Price 953.16 (Limit 952.72). How can this be if the order is sent as PlaceTrade(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 1, "Short At StopLimit"); ? In such a case, the price of the limit and stop should coincide. On backtest and dummy it's 952.72 and in IB it turns out different.
I see an order to cover 26 shares of ORLY. But the IB account is LONG ORLY, not short. So that signal failed, issuing the message "Portfolio sync could not find a position." But the signal was somehow submittied to IB, did you maybe click it and submit it manually?
>>PS: Also it is not very clear to me, here on the first screenshot you can see Order Price 953.16 (Limit 952.72). How can this be if the order is sent as PlaceTrade(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 1, "Short At StopLimit"); ? In such a case, the price of the limit and stop should coincide. On backtest and dummy it's 952.72 and in IB it turns out different.<<
I can't guess at what's happening here without seeing the Strategy.
>>PS: Also it is not very clear to me, here on the first screenshot you can see Order Price 953.16 (Limit 952.72). How can this be if the order is sent as PlaceTrade(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 1, "Short At StopLimit"); ? In such a case, the price of the limit and stop should coincide. On backtest and dummy it's 952.72 and in IB it turns out different.<<
I can't guess at what's happening here without seeing the Strategy.
QUOTE:
But the signal was somehow submittied to IB, did you maybe click it and submit it manually?
No, I didn't touch the program at all. Today I looked at the broker's report, ORLY was bought at 947.18 with a limit order, and this as you can see from the first screenshot matches my TP for the short position that should have been there originally. The strategy only enters with stoplimit orders.
From this we can conclude that for some reason the tp was executed, although initially there was no position, which is strange. Because my strategy code is like this
CODE:
Position foundPosition1 = FindOpenPosition(1); if (foundPosition1 == null) { if (side == "S") { _transaction = PlaceTrade(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 1, "Short At StopLimit"); } } else { if (orderPrice == 0.0) orderPrice = foundPosition1.BasisPrice; value = Math.Round(expandedDayATR[firstBarOfDay] * Parameters[0].AsDouble / 100.0, 2); ClosePosition(foundPosition1, OrderType.Stop, (foundPosition1.PositionType == PositionType.Long) ? orderPrice - value : orderPrice + value, "Cover at stop loss"); value = Math.Round(expandedDayATR[firstBarOfDay] * Parameters[1].AsDouble / 100.0, 2); ClosePosition(foundPosition1, OrderType.Limit, (foundPosition1.PositionType == PositionType.Long) ? orderPrice + value : orderPrice - value, "Cover at profit target"); }
As for the discrepancy in stop and limit order price, I paid attention to the timing, which means it was a manual Run Now, possibly because of that, so that explains it.
In any case, if you don't find a bug in the code I wrote, I don't see any other way out but for you to write your own reference implementation of order and position processing. What I mean is to put all the control logic on the program side, so that the strategy could be specified by a single function like PlaceTradeNew(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 1, "Short At StopLimit", StopPrice, TakeProfitPrice); and that this function would take into account both AssignAutoStopTargetPrices and GetMaxRiskStopLevel. This way you will be able to perform all the necessary tests and be sure that the code works as it should, then users can also be sure that such situations will not happen.
Ideally, such a function should also indicate how many bars the signal is valid for. That is, a maximized function that will take all the logic out of the user if that's the problem.
The code is incomplete - expandedDayATR? firstBarOfDay?
Do you still have "Live Positions" enabled?
Are you still polling for 60 minute bars?
My only real suspicion are the 60 minute bars - we've had trouble with those in the Strategy Monitor, but they should work properly now since Build 40. To be sure, I'll check IB again today.
Do you still have "Live Positions" enabled?
Are you still polling for 60 minute bars?
My only real suspicion are the 60 minute bars - we've had trouble with those in the Strategy Monitor, but they should work properly now since Build 40. To be sure, I'll check IB again today.
> The code is incomplete - expandedDayATR? firstBarOfDay?
It's running on 30m, as you can see from the Timestamp in Orders, there are 30 minute intervals.
I forcibly closed all live positions through the Flatten broker to test today with a clean slate.
In any case, please consider the possibility of an extended function, which I wrote about in the last post, to be sure that the main functionality is placed on the program and not the strategy.
CODE:
Initialize section: BarHistory dailyBars = BarHistoryCompressor.ToDaily(bars); dayATR = new ATR(dailyBars, 4); expandedDayATR = TimeSeriesSynchronizer.Synchronize(dayATR, bars); Execute section: int firstBarOfDay = bars.FirstBarDaysBack(idx, 0);
QUOTE:
Do you still have "Live Positions" enabled?
Are you still polling for 60 minute bars?
It's running on 30m, as you can see from the Timestamp in Orders, there are 30 minute intervals.
I forcibly closed all live positions through the Flatten broker to test today with a clean slate.
In any case, please consider the possibility of an extended function, which I wrote about in the last post, to be sure that the main functionality is placed on the program and not the strategy.
QUOTE:
It's running on 30m, as you can see from the Timestamp in Orders, there are 30 minute intervals.
QUOTE:Main functionality for what?
In any case, please consider the possibility of an extended function, which I wrote about in the last post, to be sure that the main functionality is placed on the program and not the strategy.
QUOTE:
Main functionality for what?
Sending an order and maintaining a position, i.e. calling one function instead of several. In PlaceTrade to also specify the price of stop loss and take profit and how many bars the signal will be actual. And further all logic including AssignAutoStopTargetPrices and GetMaxRiskStopLevel on the program side, not on the strategy like it is now. I don't see any other way to avoid these situations.
That's for today
Let's unpack these one by one:
>>Sending an order and maintaining a position, i.e. calling one function instead of several.<<
What are the several functions involved? It's hard to fathom what you're actually requesting here. In WL, you write a strategy that manages a position over its lifetime, issuing appropriate exits in the Execute method. Are you suggesting we re-architect the very approach WL uses to model trading strategies?
>>In PlaceTrade to also specify the price of stop loss and take profit<<
You'd like a PlaceTrade override that can also specify the same-bar stop and/or limit exit prices? That sounds reasonable, but it should be its own #FeatureRequest.
>>and how many bars the signal will be actual.<<
Again, you control how many bars a signal is active by coding that logic in your strategy. We're not going to move that to the program level.
>>And further all logic including AssignAutoStopTargetPrices<<
Same-bar exits aren't going to be moved to the program level, they're going to remain a strategy specific thing.
>>and GetMaxRiskStopLevel on the program side, not on the strategy like it is now. I don't see any other way to avoid these situations.<<
The maximum risk is already at the program level. It's a default indicator that you can change in Trading Preferences. It's there because using maximum risk position sizing entails having to override GetMaxRiskStopLevel to set the stop by which the position size is calculated. If a user doesn't understand that or chooses Max Risk on a strategy that doesn't override this method, we fall back to the value of the indicator that's set up in Trading Preferences.
>>Sending an order and maintaining a position, i.e. calling one function instead of several.<<
What are the several functions involved? It's hard to fathom what you're actually requesting here. In WL, you write a strategy that manages a position over its lifetime, issuing appropriate exits in the Execute method. Are you suggesting we re-architect the very approach WL uses to model trading strategies?
>>In PlaceTrade to also specify the price of stop loss and take profit<<
You'd like a PlaceTrade override that can also specify the same-bar stop and/or limit exit prices? That sounds reasonable, but it should be its own #FeatureRequest.
>>and how many bars the signal will be actual.<<
Again, you control how many bars a signal is active by coding that logic in your strategy. We're not going to move that to the program level.
>>And further all logic including AssignAutoStopTargetPrices<<
Same-bar exits aren't going to be moved to the program level, they're going to remain a strategy specific thing.
>>and GetMaxRiskStopLevel on the program side, not on the strategy like it is now. I don't see any other way to avoid these situations.<<
The maximum risk is already at the program level. It's a default indicator that you can change in Trading Preferences. It's there because using maximum risk position sizing entails having to override GetMaxRiskStopLevel to set the stop by which the position size is calculated. If a user doesn't understand that or chooses Max Risk on a strategy that doesn't override this method, we fall back to the value of the indicator that's set up in Trading Preferences.
>Are you suggesting we re-architect the very approach WL uses to model trading strategies?
I'm not trying to invent anything, I've encountered bugs and am offering solutions from the position that I see. Now for some reason positions remain unmaintained. That's why I suggested to put the whole logic of stop/tp orders on the program side, not on the strategy side. Maybe there is another solution, I am not aware of it. Here is today's example, I made a screenshot a few hours before market close. You can see that there is market data, but the strategy does not see the position, so it does not place stop and limit orders.
As a result, all 3 IB positions remained overnight, although they should have been closed according to the rules of the strategy before the market close. And moreover, they remained without stops at all.
I'm not trying to invent anything, I've encountered bugs and am offering solutions from the position that I see. Now for some reason positions remain unmaintained. That's why I suggested to put the whole logic of stop/tp orders on the program side, not on the strategy side. Maybe there is another solution, I am not aware of it. Here is today's example, I made a screenshot a few hours before market close. You can see that there is market data, but the strategy does not see the position, so it does not place stop and limit orders.
As a result, all 3 IB positions remained overnight, although they should have been closed according to the rules of the strategy before the market close. And moreover, they remained without stops at all.
So far, the only solutions I can see is to switch to "Exit orphan positions at market" and disable "use live positions". But then portfolio synchronization will be disabled, and I understand it is needed too.
And this is an example of how MaxRisk works, it is specified 0.01 on the backtest and in the strategy monitor, as well as the balance of 100k. We can see that the price of orders coincides, but the number of shares in them does not.
I don’t think moving all of this logic out of the strategy would solve the issue of a strategy not always remains in sync with reality. This is something that can happen. Perhaps the strategy received a historical fill but the live account did not due to poor liquidity at the execution price.
We developed two ways to try and handle these situations.
The first is Live Positions. When enabled, the strategy will discord any theoretical position and inject the position returned by the broker API. The limitation here is that the broker returns a single position per symbol so if you trade multiple strategies on the same symbol(s) or strategy that itself maintains multiple positions then this probably won’t work well.
Secondly we have the standard portfolio sync methods, which let you for example limit the size of the exit based on the shares in the broker reported position.. This option retains your theoretical backtest positions but adjusts the size of the signals for live trading. If the broker doesn’t report new positions in. timely manner via their API then this method can suffer.
I’m not sure if you’re trading the same symbol in multiple strategies, but that could explain the issues with Live Positions. It’s fine to turn off Live Positions if the outcome is better for your trading style.
It would be good to isolate why some of your positions were failing to sync, leading to unwanted exposure. The only explanation that’s coming to mind is broker latency but I’ll check in with Cone who’s more the IB expert and see if he has any other ideas.
We developed two ways to try and handle these situations.
The first is Live Positions. When enabled, the strategy will discord any theoretical position and inject the position returned by the broker API. The limitation here is that the broker returns a single position per symbol so if you trade multiple strategies on the same symbol(s) or strategy that itself maintains multiple positions then this probably won’t work well.
Secondly we have the standard portfolio sync methods, which let you for example limit the size of the exit based on the shares in the broker reported position.. This option retains your theoretical backtest positions but adjusts the size of the signals for live trading. If the broker doesn’t report new positions in. timely manner via their API then this method can suffer.
I’m not sure if you’re trading the same symbol in multiple strategies, but that could explain the issues with Live Positions. It’s fine to turn off Live Positions if the outcome is better for your trading style.
It would be good to isolate why some of your positions were failing to sync, leading to unwanted exposure. The only explanation that’s coming to mind is broker latency but I’ll check in with Cone who’s more the IB expert and see if he has any other ideas.
No ideas really. I use this everyday with IB and I've done many thousands of trades with live and paper accounts. Just last week, as you (Glitch) might recall, I marveled at how great Auto Trade works in WL8.
Initially (and pre-Build 40), Live Positions worked only with strategies that used PositionTag 0. I'm quite sure I made a change and tested it to be able to use other tags. Nonetheless, if there's not a good reason to use 1 to distiguish positions, change it to use PositionTag 0 - and FindOpenPosition(0). I don' think it will make a difference, but at least it's something to try.
Apart from that, can you show us your logic to get out at the close?
Getting out at the close can be tricky with Intraday strategies... and from your settings in Post #34, it looks like you're set up to get out at 5 minutes (300s) before the close with a market order - provided that your strategy issues a MarketClose order at 3:30pm.
Initially (and pre-Build 40), Live Positions worked only with strategies that used PositionTag 0. I'm quite sure I made a change and tested it to be able to use other tags. Nonetheless, if there's not a good reason to use 1 to distiguish positions, change it to use PositionTag 0 - and FindOpenPosition(0). I don' think it will make a difference, but at least it's something to try.
Apart from that, can you show us your logic to get out at the close?
Getting out at the close can be tricky with Intraday strategies... and from your settings in Post #34, it looks like you're set up to get out at 5 minutes (300s) before the close with a market order - provided that your strategy issues a MarketClose order at 3:30pm.
QUOTE:
Positions worked only with strategies that used PositionTag 0.
The assumption about PositionTag makes a lot of sense. I remember encountering this back on the Binance adapter. Apparently it doesn't work perfectly here either. Anyway, I rewrote the code not to use PositionTag at all and now it is more concise and clear.
CODE:
if (LastOpenPosition != null) { if (orderPrice == 0.0) orderPrice = LastOpenPosition.BasisPrice; value = Math.Round(expandedDayATR[firstBarOfDay] * Parameters[0].AsDouble / 100.0, 2); ClosePosition(LastOpenPosition, OrderType.Stop, (LastOpenPosition.PositionType == PositionType.Long) ? orderPrice - value : orderPrice + value, "Close at stop loss"); value = Math.Round(expandedDayATR[firstBarOfDay] * Parameters[1].AsDouble / 100.0, 2); ClosePosition(LastOpenPosition, OrderType.Limit, (LastOpenPosition.PositionType == PositionType.Long) ? orderPrice + value : orderPrice - value, "Close at profit target"); } else { if (side == "L") PlaceTrade(bars, TransactionType.Buy, OrderType.StopLimit, orderPrice, 0, "Buy At StopLimit"); else if (side == "S") PlaceTrade(bars, TransactionType.Short, OrderType.StopLimit, orderPrice, 0, "Short At StopLimit"); }
QUOTE:
Apart from that, can you show us your logic to get out at the close?
I don't use the MarketClose order as it overrides the stop order, so I just close at Market before close.
CODE:I will test this version today and if there are no problems with LastOpenPosition, I don't see why this code shouldn't work.
if (bars.DateTimes[idx].GetTime() >= 1530) { if (LastOpenPosition != null) ClosePosition(LastOpenPosition, OrderType.Market, 0, "Close position at market close"); return; }
If you group the orders with the same CancelationCode, then the MarketClose order ("Use MOC" must be unchecked) will be held in the "WaitForClose" state until the number of seconds you specified before close. At that time, the Stop/Limit orders are canceled and the the market order to close the position will be Submitted to the broker.
CODE:
if (LastOpenPosition != null) { if (orderPrice == 0.0) orderPrice = LastOpenPosition.BasisPrice; Backtester.CancelationCode = 142; value = Math.Round(expandedDayATR[firstBarOfDay] * Parameters[0].AsDouble / 100.0, 2); ClosePosition(LastOpenPosition, OrderType.Stop, (LastOpenPosition.PositionType == PositionType.Long) ? orderPrice - value : orderPrice + value, "Close at stop loss"); Backtester.CancelationCode = 142; value = Math.Round(expandedDayATR[firstBarOfDay] * Parameters[1].AsDouble / 100.0, 2); ClosePosition(LastOpenPosition, OrderType.Limit, (LastOpenPosition.PositionType == PositionType.Long) ? orderPrice + value : orderPrice - value, "Close at profit target"); if (bars.DateTimes[idx].GetTime() >= 1530) { Backtester.CancelationCode = 142; if (LastOpenPosition != null) ClosePosition(LastOpenPosition, OrderType.MarketClose, 0, "Close position at market close"); return; } }
With the replacement of PositionTag with LastOpenPosition works like a charm, no unmaintained positions or errors in the order manager so far!
What remains to be dealt with is MaxRisk, what is described in Post #44. From what figure does the risk calculation for real trading come from? Is it Account value from the broker or Starting capital from the settings or some other?
What remains to be dealt with is MaxRisk, what is described in Post #44. From what figure does the risk calculation for real trading come from? Is it Account value from the broker or Starting capital from the settings or some other?
Currently, it must be the backtest equity.
We've just enabled the Max Risk Pct PosSizer types to use Broker-reported account value for Build 48.
We've just enabled the Max Risk Pct PosSizer types to use Broker-reported account value for Build 48.
@ww5 -
Live Position sync when using PositionTags other than 0 should work correctly in Build 49. Previously, the sync was being too restrictive.
Live Position sync when using PositionTags other than 0 should work correctly in Build 49. Previously, the sync was being too restrictive.
These days I tested the code from Post #48 in all kinds of situations, it works perfectly. I also tested Max Risk Pct PosSizer, it works great too, the real trade coincides with the backtest.
Your Response
Post
Edit Post
Login is required