- ago
I have a strategy that exports a text file of backtest performance data to a Windows file. It is run in the BacktestComplete() method.

It runs fine in standalone mode (SA) but AppendText will not output the data in a foreach loop when run in the Stategy Monitor (SM).

Here's the relevant code:
CODE:
         string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);                filename = folderPath + "/OneDrive/Wealth-Lab/" + "WL VarLev Out.txt";          File.Delete(filename);          using (writer = File.CreateText(filename))          {             writer.WriteLine("Symbol" + sep + "K%" + sep + "Net Profit" + sep                + "Trades" + sep + "Win" + sep + "Lose" + sep                + "Win Rate" + sep + "Loss Rate" + sep                + "Avg Win" + sep + "Avg Loss" + sep                + "P/O Ratio" + sep + "Open", true);          }          using (writer = File.AppendText(filename))          {             writer.WriteLine(filename);                                  foreach(IndexLevSymPerf sp in spList)             {                Thread.Sleep(500);                writer.WriteLine("hello");                writer.WriteLine(sp.symbol + sep + Math.Round(sp.k, 2) + sep                   + string.Format("{0:C}", sp.profit) + sep                   + sp.trades + sep + sp.win + sep + sp.loss + sep                   + string.Format("{0:P}", sp.winPct) + sep                   + string.Format("{0:P}", sp.lossPct) + sep                   + Math.Round(sp.nppAvg, 2) + "%" + sep                   + Math.Round(sp.nlpAvg, 2) + "%" + sep                   + Math.Round(sp.poRatio, 2) + sep + sp.open, true);             }             }

I have tried quite a few things to debut but I am stumped. The code above includes things I added to help debug. When run in the SM, it will always successfully delete . and create a file and write the header. It will also write out the AppendText info *outside* of the foreach loop. It will not write out any data within the foreach loop, including text data I inserted ("hello")

Here's what running in the SM produces from this code:
CODE:
Symbol   K%   Net Profit   Trades   Win   Lose   Win Rate   Loss Rate   Avg Win   Avg Loss   P/O Ratio   Open C:\Users\innertrader/OneDrive/Wealth-Lab/WL VarLev Out.txt


I have none of these issues when run SA. I put timing delays in but it didn't make any difference. Unless you've heard of this type of issue before, please let me know if you have any ideas how I can troubleshoot further.
0
337
Solved
11 Replies

Reply

Bookmark

Sort
Cone8
 ( 22.68% )
- ago
#1
I'd conclude that spList is empty- at least it's empty in the last run, but you start by deleting the file every time. Also, there's no guarantee that there will be only one backtest.

1. Is spList a static variable?
2. At least start by checking that spList has something in it before you do anything else (like deleting the file).

... and don't stop the thread for a half second in that loop.
0
- ago
#2
Yes, spList is a static variable.

I modified the code to test for spList == null
CODE:
         string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);                filename = folderPath + "/OneDrive/Wealth-Lab/" + "WL VarLev Out.txt";          File.Delete(filename);          using (writer = File.CreateText(filename))          {             writer.WriteLine("Symbol" + sep + "K%" + sep + "Net Profit" + sep                + "Trades" + sep + "Win" + sep + "Lose" + sep                + "Win Rate" + sep + "Loss Rate" + sep                + "Avg Win" + sep + "Avg Loss" + sep                + "P/O Ratio" + sep + "Open", true);          }          using (writer = File.AppendText(filename))          {             writer.WriteLine(filename);             writer.WriteLine("Is spList null?");             writer.WriteLine(spList == null);             if (spList != null)                writer.WriteLine("spList count is " + spList.Count);             foreach(IndexLevSymPerf sp in spList)             {                writer.WriteLine("hello");                writer.WriteLine(sp.symbol + sep + Math.Round(sp.k, 2) + sep                   + string.Format("{0:C}", sp.profit) + sep                   + sp.trades + sep + sp.win + sep + sp.loss + sep                   + string.Format("{0:P}", sp.winPct) + sep                   + string.Format("{0:P}", sp.lossPct) + sep                   + Math.Round(sp.nppAvg, 2) + "%" + sep                   + Math.Round(sp.nlpAvg, 2) + "%" + sep                   + Math.Round(sp.poRatio, 2) + sep + sp.open, true);             }             }

Here is what the output looks like when I run it standalone
CODE:
Symbol   K%   Net Profit   Trades   Win   Lose   Win Rate   Loss Rate   Avg Win   Avg Loss   P/O Ratio   Open C:\Users\innertrader/OneDrive/Wealth-Lab/WL VarLev Out.txt                                  Is spList null?                                  FALSE                                  spList count is 7                                  hello                                  QQQ   0.21   $9,340.64    9   6   3   66.67%   33.33%   2.48%   -3.43%   0.72   FALSE hello                                  TQQQ   0.8   $157,145.78    6   5   1   83.33%   16.67%   6.46%   -1.25%   5.15   FALSE hello                                  UWM   0   ($5,598.70)   1   0   1   0.00%   0.00%   0%   0%   0   FALSE hello                                  UPRO   0.59   $141,806.22    4   3   1   75.00%   25.00%   15.05%   -9.38%   1.6   FALSE hello                                  IVV   0   $16,957.43    3   3   0   0.00%   0.00%   0%   0%   0   FALSE hello                                  EDC   0   $17,109.59    2   2   0   0.00%   0.00%   0%   0%   0   FALSE hello                                  EEM   0   $1,242.73    1   1   0   0.00%   0.00%   0%   0%   0   FALSE


Here's what it looks like when I run it in the Strategy Monitor:
CODE:
Symbol   K%   Net Profit   Trades   Win   Lose   Win Rate   Loss Rate   Avg Win   Avg Loss   P/O Ratio   Open C:\Users\innertrader/OneDrive/Wealth-Lab/WL VarLev Out.txt                                  Is spList null?                                  FALSE                                  spList count is 0                                 


Note that WriteLine only fails within the foreach loop, and that only happens when it is running in the Strategy Monitor.

Addendum: I just noticed that spList has 0 count, even though it does not test null. Thanks for leading down that path.

So, now I guess the question is why is spList empty only when run in the SM?
0
Glitch8
 ( 12.83% )
- ago
#3
Nothing is failing. The Count of your list is zero so there was nothing in the list during the final run of the strategy in the SM.

You haven’t provided the full code so we can’t begin to guess why.
0
- ago
#4
I am running this in the BacktestComplete method., so there is only one run, not a final run.

Immediately prior to this code, I pass spList as a variable to another method and I just created another output test that confirms it is not calculating properly. confirming that spList must be empty. It's challenging that I can't use the debug log to try to figure out what's going on.

I don't understand why spList is becoming empty, and why it only happens when it's run in the SM.
0
Cone8
 ( 22.68% )
- ago
#5
Read this very carefully -

I'd conclude that spList is empty- at least it's empty in the last run, but you start by deleting the file every time. Also, there's no guarantee that there will be only one backtest.

The take away is that you should make sure that spList.Count != 0 before you delete the file or even continue with any other action.
0
- ago
#6
I modified the code as you suggested. This code runs in BacktestComplete()
CODE:
         if (spList.Count > 0)          {             using (writer = File.CreateText(filename))             {                writer.WriteLine("Symbol" + sep + "K%" + sep + "Net Profit" + sep                   + "Trades" + sep + "Win" + sep + "Lose" + sep                   + "Win Rate" + sep + "Loss Rate" + sep                   + "Avg Win" + sep + "Avg Loss" + sep                   + "P/O Ratio" + sep + "Open", true);             }             using (writer = File.AppendText(filename))             {                foreach (IndexLevSymPerf sp in spList)                {                   writer.WriteLine(sp.symbol + sep + Math.Round(sp.k, 2) + sep                      + string.Format("{0:C}", sp.profit) + sep                      + sp.trades + sep + sp.win + sep + sp.loss + sep                      + string.Format("{0:P}", sp.winPct) + sep                      + string.Format("{0:P}", sp.lossPct) + sep                      + Math.Round(sp.nppAvg, 2) + "%" + sep                      + Math.Round(sp.nlpAvg, 2) + "%" + sep                      + Math.Round(sp.poRatio, 2) + sep + sp.open, true);                }                }          }

The result is that it never creates a file or updates it when run in SM. Works fine Stand Alone (SA).

I went back to a much earlier version of this routine and it had the same problem. Apparently, I never tested this code from the SM to insure it was outputting correctly.

I modified the earlier version to test for list variables being empty. I eliminated the foreach loop from the picture. Here's the relevant code, also run in BacktestComplete().
CODE:
         string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);          string filename = folderPath + "/OneDrive/Options/" + "WL VarLev Out.txt";          string sep = "\t"; //tab delimited          lstPositionsPortfolio = GetPositionsAllSymbols();          using (StreamWriter writer3 = File.CreateText(folderPath + "/OneDrive/Options/" + "Tester.txt"))          {             writer3.WriteLine("lstPositionsPortfolio Count is " + lstPositionsPortfolio.Count, true);          }

Here's the output when run SA

Here's the output when run in the SM

Here's the static list variable declaration
CODE:
      private static List<Position> lstPositionsPortfolio;


I can't figure out why these lists are empty *only* when run in the SM. It's especially perplexing that lstPositionsPortfolio is empty since
CODE:
lstPositionsPortfolio = GetPositionsAllSymbols();

is run just above it in the same scope. It's as if the list is not being populated when run in the SM. The backtest is showing positions when run in the SM. I can't tell if there are really any positions when run in the SM. Maybe there aren't or GetPositionsAllSymbols() doesn't think there are.

Correction to paragraph above:
QUOTE:
The backtest is showing positions when run in the SM.

should be
QUOTE:
The backtest is showing positions when run SA.
0
Cone8
 ( 22.68% )
- ago
#7
Since we can't see what your doing or how or when something is added to the list, I'll make my last guess on the subject:
Do you have "Use Live Positions" checked in the Trading Preferences?
0
- ago
#8
No
0
Cone8
 ( 22.68% )
- ago
#9
Here's a minimal example based on your code. Does it work for you?

Note - and maybe this is the problem - I noticed that you must REMOVE the Strategy from the S. Monitor and add it again to get an updated copy of edits to a Strategy.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using System.IO; namespace WealthScript12 { public class MyStrategy : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) {          StartIndex = 20; } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) {             PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else {             Position p = LastPosition; if (p.EntryBar == idx)                spList.Add(p); } }       public override void BacktestBegin()       {          //start fresh          spList = new List<Position>();       }        public override void BacktestComplete() {                                 if (spList.Count > 0)          {             using (writer = File.CreateText(filename))             {                writer.WriteLine("b1 Backtester.ExecutionMode = " + Backtester.ExecutionMode );                writer.WriteLine("spList.Count = " + spList.Count);                writer.WriteLine("Symbol" + sep + "Net Profit" );             }             using (writer = File.AppendText(filename))             {                foreach (Position sp in spList)                {                   writer.WriteLine(sp.Symbol + sep                    + string.Format("{0:C}", sp.Profit));                }             }          } }       string filename = @"C:\Data\Test.txt";       StreamWriter writer;       string sep = "\t";       static List<Position> spList;     } }
0
- ago
#10
Thank you for this.
QUOTE:
I noticed that you must REMOVE the Strategy from the S. Monitor and add it again to get an updated copy of edits to a Strategy.

Yes, I know. I have been doing that.
QUOTE:
Does it work for you?

Yes, it does. SA and SM same output. I will look deeper into my code to see if I can figure out what's different.
0
- ago
#11
@Cone
This was a total OE. The only thing I got right was the possibility that there were no positions created when running in the SM. But why only in the SM? The reason is I failed to realize I had to set the backtest timeframe in the SM settings to match the strategy running SA.

Since this is a bullish strategy, and the market has been down so long, the last trades were in 2021. The default setting of 1 year in the SM settings accurately generated "no trades" and hence an empty positions list.

It's working now that I set the timeframe correctly. Good news is there's no nasty SM bug to fix.

The sample test program you sent forced me down another path. Sorry for the misdirect and thanks for the help you provided. :)
1
Best Answer

Reply

Bookmark

Sort