- ago
Hello, I have noticed that OpenPositions is not updated untill next bar (idx) but ActivePositions (WL6) is updated immediately, I mean:

WL6 Code:
CODE:
for(int bar = 20; bar < Bars.Count; bar++)          {             if (bar ==25)             {                   PrintDebug("Before Open Long in bar " + bar + " ActivePositions.Counts = " + ActivePositions.Count);                   BuyAtMarket(bar );                   PrintDebug("After Open Long in bar " + bar + " ActivePositions.Counts = " + ActivePositions.Count);                }             if (bar == 30 )             {                   PrintDebug("Before Close Position Long in bar " + bar + " ActivePositions.Counts = " + ActivePositions.Count);                      SellAtMarket(bar + 1, LastPosition);                PrintDebug("After Close Position Long in bar " + bar + " ActivePositions.Counts = " + ActivePositions.Count);             }


Debug Log:
Before Open Long in bar 25 ActivePositions.Counts = 0
After Open Long in bar 25 ActivePositions.Counts = 1
Before Close Position Long in bar 30 ActivePositions.Counts = 1
After Close Position Long in bar 30 ActivePositions.Counts = 0

WL7 Code:
CODE:
   if (idx == 25)          {             WriteToDebugLog("Before Open Long in bar " + idx + " ActivePositions.Counts = " + OpenPositions.Count);             PlaceTrade(bars,TransactionType.Buy, OrderType.Market);             WriteToDebugLog("After Open Long in bar " + idx + " ActivePositions.Counts = " + OpenPositions.Count);          }          if (idx == 26)          {             WriteToDebugLog("Bar " + idx + " ActivePositions.Counts = " + OpenPositions.Count);          }          if (idx == 30)          {             WriteToDebugLog("Before Close Position Long in bar " + idx + " ActivePositions.Counts = " + OpenPositions.Count);             ClosePosition( LastPosition,OrderType.Market);             WriteToDebugLog("After Close Position Long in bar " + idx + " ActivePositions.Counts = " + OpenPositions.Count);             WriteToDebugLog ("HasOpenPositions ????? "+ HasOpenPosition(bars, PositionType.Long) );          }


Debug Log:
--SPY--
Before Open Long in bar 25 ActivePositions.Counts = 0
After Open Long in bar 25 ActivePositions.Counts = 0
Bar 26 ActivePositions.Counts = 1
Before Close Position Long in bar 30 ActivePositions.Counts = 1
After Close Position Long in bar 30 ActivePositions.Counts = 1
HasOpenPositions ????? True

Is there a way to update OpenPositions (WL7) inmediately,
I I may need to detect it in the same bar,
For example after closing a position I need to detect it to open a new one:

ClosePosition( LastPosition,OrderType.Market);
if (!HasOpenPosition(bars, PositionType.Long))
{
//do something
}
0
964
Solved
3 Replies

Reply

Bookmark

Sort
- ago
#1
I believe this is due to the fact that WL7's backtesting engine has been revamped compared to WL6.
0
Cone8
 ( 25.44% )
- ago
#2
Eugene's right. WL7 is more realistic in this sense. Positions are not actually created on the current bar, only their Transaction (order) is.

If your script relied on knowing about Positions created on the next bar, you'll need to adjust the logic to compensate for that in a realistic way. If you have a specific scenario that you need help with, let us know.

Generally, you'll just need to create a private class variable to store something to retrieve on any bar. If you need all symbols in the backtest to access the same variable, make it static - like in this example -

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class MyStrategy : UserStrategyBase {       static int _allSymbolsCanAccess = 0;        public override void Initialize(BarHistory bars) {       } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) {          //count the number of bars processed          _allSymbolsCanAccess++; } public override void BacktestComplete() { base.BacktestComplete();          WriteToDebugLog("Total Bars Processed: " + _allSymbolsCanAccess); } } }


1
Best Answer
- ago
#3
And if you have two separate instances (Chart windows) of MyStrategy, will be code below be a problem?
CODE:
public class MyStrategy : UserStrategyBase { static int _allSymbolsCanAccess = 0;
I guess my point would be to declare a "common" variable as non-static in the constructor of MyStrategy{}.

Hmm. I may have to back peddle on my suggestion. It depends on what is meant by "common" and what is thread safe in WL. This example is tricky. :(

For thread safety, WL may require a strategy thread to completely execute before it time slices to a different strategy instance (i.e. no preemptive time slicing/scheduling). In this case, sharing variables between strategy instances are fine because all shared variables are updated atomically (on the same time slice). In the above example, we have only one shared variable, so thread safely is less of an issue. But what if we had two shared variables? Can both be updated atomically (on the same time slice)?

We worry about such things in real-time system design.

---
UPDATE: After thinking about this more,... if you're only using shared common variables for data logging as in Cone's example, I don't think you have to worry about thread safety. In contrast, if you have more than one shared variable that controls the outcome of the strategy (e.g. like alters the program flow of the strategy code), then thread safety becomes an issue. For example, if the two or so shared variables controlling program flow don't get updated together (atomically), the strategy could enter a weird state (deadlocked state?) that was never planned, which could poison your simulation results.

Start a new topic "Non-deterministic strategy bugs" if you want to talk more about possible thread safety issues with strategies.
0

Reply

Bookmark

Sort