- ago
I have a monthly trading strategy that give daily signals. However, I want it to give signals only on the 1st trading day of the month. Sometimes 1st day of month falls on the weekend, so I need to know to create the buy signal on the next Monday, etc.

What code can I use to setup this filter. Such as :

CODE:
//I need code for this next line that only makes trades on 1st trading day, or filters such as an exception to only trade on that day if (bars.DateTimes[idx].day == 2........30) return;       _transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, 0, "Buy At Market (1)");             }
0
605
Solved
19 Replies

Reply

Bookmark

Sort
Cone8
 ( 28.32% )
- ago
#1
CODE:
            if (bars.DateTimes[idx].IsLastTradingDayOfMonth(bars))             {                _transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, 0, "Buy At Market (1)");             }
0
- ago
#2
This code is giving me an errror:

The name 'idx' does not exist in the current context.

CODE:
         foreach (BarHistory bh in buys)          {             if (!HasOpenPosition(bh, PositionType.Long))             {                if (bh.DateTimes[idx].IsLastTradingDayOfMonth(bh)) // Larry changed                {                   Transaction t = PlaceTrade(bh, TransactionType.Buy, OrderType.Market);                }                          }          }


I can't figure out what to change for idx. Any suggestions?

Thank you,
Larry
0
- ago
#3
QUOTE:
The name 'idx' does not exist in the current context.

It must exist if you're pasting the code into the Execute() block - unless you explicitly renamed the "idx" in its signature to say "bar" (yes, this is possible). But you seem to be doing it all of a sudden in PostExecute or PreExecute (because your title post isn't indicative of that), why?
0
Cone8
 ( 28.32% )
- ago
#4
With your newly-added context, you'd do it like this -

CODE:
         foreach (BarHistory bh in buys)          {             if (!HasOpenPosition(bh, PositionType.Long))             {                int idx = GetCurrentIndex(bh);                if (bh.DateTimes[idx].IsLastTradingDayOfMonth(bh))                {                   Transaction t = PlaceTrade(bh, TransactionType.Buy, OrderType.Market);                }             }          }
0
- ago
#5
Eugene and Cone,

Works great.

Thank you for your help.

- Larry
0
- ago
#6
Based on the last snippet, here is the new modified snippet to close the trade on the last trading day of the month. This is not working. Can you please help.




Thank you,
Larry







0
Cone8
 ( 28.32% )
- ago
#7
Use pos.Bars, not pos, wherever a BarHistory is required.. on lines 82 and 83
0
- ago
#8
Cone,

That worked well for the Run on monthly bars.

Thank you,

For some reason when changing the data scale from Monthly to Daily, on the Run, I am getting this message for line 97.



Also, on line 83, I want to change the variable from IsLastTradingDayOfMonth to IsFirstTradingDayOfMonth. for the Sell signal, so that it closes on Last trading day of the month.



Thank you,

Larry
0
Cone8
 ( 28.32% )
- ago
#9
For a shot in the dark, just try putting this in Initialize().

CODE:
StartIndex = 30;


There is no "IsFirstTradingDayOfMonth" method (that's why it doesn't pop up with the Intellisense when you type the dot). Anyway, it's pretty easy to derive from the other one -

CODE:
bool isFirstTradingDayOfMonth = idx > 0 ? bars.DateTimes[idx - 1].IsLastTradingDayOfMonth(bars) : false;
0
- ago
#10
Can you please tell me what the issue is on line 44 and 98.

Here is code. Still causing me issues. I am trying to resolve the error on line 44 and I think also on line 98.

Here are the errors and then the code:



Your help is appreciated.

Thank you,
Larry

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 {    public class Rotation : UserStrategyBase    {       public Rotation()       {          AddParameter("ROC Period", ParameterType.Int32, 3, 1, 10, 1); // Default = 3          AddParameter("SMA Period", ParameterType.Int32, 10, 3, 15, 1); // Default = 3          AddParameter("n Symbols", ParameterType.Int32, 3, 2, 5, 1); // Default = 3       }       ROC _avgROC;       SMA _smaBenchmark;       BarHistory _bmBars;       string _seriesKey = "Average ROC";       string _bmSymbol = "^GSPC";             //the list of symbols that we should buy each bar       private static List<BarHistory> buys = new List<BarHistory>();       //create the weight indicator and stash it into the BarHistory object for reference in PreExecute       public override void Initialize(BarHistory bars)       {          StartIndex = Math.Max(Parameters[0].AsInt, Parameters[1].AsInt);          _avgROC = ROC.Series(bars.Close, Parameters[0].AsInt);          bars.Cache[_seriesKey] = _avgROC;          _bmBars = GetHistory(bars, _bmSymbol, "Major U.S. and world indices");          _smaBenchmark = SMA.Series(_bmBars.Close, Parameters[1].AsInt);       }       public override void PreExecute(DateTime dt, List<BarHistory> participants)       {       // LARRY PUT THIS IN AS A TEST TO CREATE THE VARIABLE isFirstTradingDayOfMonth       bool isFirstTradingDayOfMonth = idx > 0 ? bars.DateTimes[idx - 1].IsLastTradingDayOfMonth(bars) : false;                    //store the symbols' _avgROC value in their BarHistory instances          foreach (BarHistory bh in participants)          {             TimeSeries symbolRoc = (TimeSeries)bh.Cache[_seriesKey];             int idx = GetCurrentIndex(bh);             double rocVal = symbolRoc[idx];             if (idx <= symbolRoc.FirstValidIndex)                rocVal = -1.0e6;             bh.UserData = rocVal; //save the current _avgROC value along with the BarHistory instance          }          //sort the participants by _avgROC value (highest to lowest)          participants.Sort((a, b) => b.UserDataAsDouble.CompareTo(a.UserDataAsDouble));          //keep the top 3 symbols          buys.Clear();          //market filter          int currentBar = GetCurrentIndex(_bmBars);          if (_bmBars.Close[currentBar] > _smaBenchmark[currentBar])          {             for (int n = 0; n < Parameters[2].AsInt; n++)             {                if (n >= participants.Count)                   break;                buys.Add(participants[n]);                int idx = GetCurrentIndex(participants[n]);                DateTime dte = participants[n].DateTimes[idx];             }          }          foreach (Position pos in OpenPositionsAllSymbols)          {             if (!buys.Contains(pos.Bars))             {                int idx = GetCurrentIndex(pos.Bars);                if (pos.Bars.DateTimes[idx].IsLastTradingDayOfMonth(pos.Bars))                {                   ClosePosition(pos, OrderType.Market);                }             }          }          foreach (BarHistory bh in buys)          {             if (!HasOpenPosition(bh, PositionType.Long))             {                if (!HasOpenPosition(bh, PositionType.Long))                {                   int idx = GetCurrentIndex(bh);                   if (bh.DateTimes[idx].IsFirstTradingDayOfMonth(bh)) // this code makes buy/sell signals only on 1st day of the month, so I don't get daily trade signals repeating during the month                   {                      Transaction t = PlaceTrade(bh, TransactionType.Buy, OrderType.Market);                   }                }             }                          }       }       public override void Execute(BarHistory bars, int idx)       {       }    } }
0
Cone8
 ( 28.32% )
- ago
#11
Try this -

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 {    public class Rotation : UserStrategyBase    {       public Rotation()       {          AddParameter("ROC Period", ParameterType.Int32, 3, 1, 10, 1); // Default = 3          AddParameter("SMA Period", ParameterType.Int32, 10, 3, 15, 1); // Default = 3          AddParameter("n Symbols", ParameterType.Int32, 3, 2, 5, 1); // Default = 3       }       ROC _avgROC;       SMA _smaBenchmark;       BarHistory _bmBars;       string _seriesKey = "Average ROC";       string _bmSymbol = "^GSPC";       //the list of symbols that we should buy each bar       private static List<BarHistory> buys = new List<BarHistory>();       //create the weight indicator and stash it into the BarHistory object for reference in PreExecute       public override void Initialize(BarHistory bars)       {          StartIndex = Math.Max(Parameters[0].AsInt, Parameters[1].AsInt);          _avgROC = ROC.Series(bars.Close, Parameters[0].AsInt);          bars.Cache[_seriesKey] = _avgROC;          _bmBars = GetHistory(bars, _bmSymbol, "Major U.S. and world indices");          _smaBenchmark = SMA.Series(_bmBars.Close, Parameters[1].AsInt);       }       public override void PreExecute(DateTime dt, List<BarHistory> participants)       {          //store the symbols' _avgROC value in their BarHistory instances          foreach (BarHistory bh in participants)          {             TimeSeries symbolRoc = (TimeSeries)bh.Cache[_seriesKey];             int idx = GetCurrentIndex(bh);             double rocVal = symbolRoc[idx];             if (idx <= symbolRoc.FirstValidIndex)                rocVal = -1.0e6;             bh.UserData = rocVal; //save the current _avgROC value along with the BarHistory instance          }          //sort the participants by _avgROC value (highest to lowest)          participants.Sort((a, b) => b.UserDataAsDouble.CompareTo(a.UserDataAsDouble));          //keep the top 3 symbols          buys.Clear();          //market filter          int currentBar = GetCurrentIndex(_bmBars);          if (_bmBars.Close[currentBar] > _smaBenchmark[currentBar])          {             for (int n = 0; n < Parameters[2].AsInt; n++)             {                if (n >= participants.Count)                   break;                buys.Add(participants[n]);                int idx = GetCurrentIndex(participants[n]);                DateTime dte = participants[n].DateTimes[idx];             }          }          foreach (Position pos in OpenPositionsAllSymbols)          {             if (!buys.Contains(pos.Bars))             {                int idx = GetCurrentIndex(pos.Bars);                if (pos.Bars.DateTimes[idx].IsLastTradingDayOfMonth(pos.Bars))                {                   ClosePosition(pos, OrderType.Market);                }             }          }          foreach (BarHistory bh in buys)          {             if (!HasOpenPosition(bh, PositionType.Long))             {                int idx = GetCurrentIndex(bh);                // LARRY PUT THIS IN AS A TEST TO CREATE THE VARIABLE isFirstTradingDayOfMonth                bool isFirstTradingDayOfMonth = idx > 0 ? bh.DateTimes[idx - 1].IsLastTradingDayOfMonth(bh) : false;                if (isFirstTradingDayOfMonth) // this code makes buy/sell signals only on 1st day of the month, so I don't get daily trade signals repeating during the month                {                   Transaction t = PlaceTrade(bh, TransactionType.Buy, OrderType.Market);                }             }          }       }       public override void Execute(BarHistory bars, int idx)       {       }    } }
0
- ago
#12
Cone,

Can you please check this. I like to run your script on daily bars and I am getting an error:

Thank you for your help.

Larry

Here is strategy settings:



Here is error message:

0
- ago
#13
The problem was in the loop that goes through OpenPositionsAllSymbols. I believe it is not valid to use GetCurrentIndex on those symbols, because a symbol may not be part of the current set of participants of the PreExecute. The problem seems to occur if the symbol history is exhausted prior to the last date of the back test.

So, here is the fix...

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 {    public class Rotation : UserStrategyBase    {       public Rotation()       {          AddParameter("ROC Period", ParameterType.Int32, 3, 1, 10, 1); // Default = 3          AddParameter("SMA Period", ParameterType.Int32, 10, 3, 15, 1); // Default = 3          AddParameter("n Symbols", ParameterType.Int32, 3, 2, 5, 1); // Default = 3       }       ROC _avgROC;       SMA _smaBenchmark;       BarHistory _bmBars;       string _seriesKey = "Average ROC";       string _bmSymbol = "^GSPC";       //the list of symbols that we should buy each bar       private static List<BarHistory> buys = new List<BarHistory>();       //create the weight indicator and stash it into the BarHistory object for reference in PreExecute       public override void Initialize(BarHistory bars)       {          StartIndex = Math.Max(Parameters[0].AsInt, Parameters[1].AsInt);          _avgROC = ROC.Series(bars.Close, Parameters[0].AsInt);          bars.Cache[_seriesKey] = _avgROC;          _bmBars = GetHistory(bars, _bmSymbol, "Major U.S. and world indices");          _smaBenchmark = SMA.Series(_bmBars.Close, Parameters[1].AsInt);       }       public override void PreExecute(DateTime dt, List<BarHistory> participants)       {          //store the symbols' _avgROC value in their BarHistory instances          foreach (BarHistory bh in participants)          {             TimeSeries symbolRoc = (TimeSeries)bh.Cache[_seriesKey];             int idx = GetCurrentIndex(bh);             double rocVal = symbolRoc[idx];             if (idx <= symbolRoc.FirstValidIndex)                rocVal = -1.0e6;             bh.UserData = rocVal; //save the current _avgROC value along with the BarHistory instance          }          //sort the participants by _avgROC value (highest to lowest)          participants.Sort((a, b) => b.UserDataAsDouble.CompareTo(a.UserDataAsDouble));          //keep the top 3 symbols          buys.Clear();          //market filter          int currentBar = GetCurrentIndex(_bmBars);          if (_bmBars.Close[currentBar] > _smaBenchmark[currentBar])          {             for (int n = 0; n < Parameters[2].AsInt; n++)             {                if (n >= participants.Count)                   break;                buys.Add(participants[n]);                int idx = GetCurrentIndex(participants[n]);                DateTime dte = participants[n].DateTimes[idx];             }          }          foreach (Position pos in OpenPositionsAllSymbols)          {             if (!buys.Contains(pos.Bars))             {                // find the relevant bar for the given current date                int idx = pos.Bars.IndexOf(dt, true);                if (idx >= 0 && pos.Bars.DateTimes[idx].IsLastTradingDayOfMonth(pos.Bars))                {                   ClosePosition(pos, OrderType.Market);                }                }          }          foreach (BarHistory bh in buys)          {             if (!HasOpenPosition(bh, PositionType.Long))             {                int idx = GetCurrentIndex(bh);                // LARRY PUT THIS IN AS A TEST TO CREATE THE VARIABLE isFirstTradingDayOfMonth                bool isFirstTradingDayOfMonth = idx > 0 ? bh.DateTimes[idx - 1].IsLastTradingDayOfMonth(bh) : false;                if (isFirstTradingDayOfMonth) // this code makes buy/sell signals only on 1st day of the month, so I don't get daily trade signals repeating during the month                {                   Transaction t = PlaceTrade(bh, TransactionType.Buy, OrderType.Market);                }             }          }       }       public override void Execute(BarHistory bars, int idx)       {       }    } }
0
Best Answer
- ago
#14
Paul,

Worked great.

Thank you so much.

This strategy has been driving me crazy for months.... finally.... lol

Cone, Volker and Eugene,

Thank you so much for your patience and help.
You guys are the best.
- Larry
1
- ago
#15
Based on the above code, I am getting an interesting quirk. I am expecting 5 trade signals per month. But it looks like 3 trade signals from last month were not closed and are being held over for this month.

Thank you,
Larry


0
- ago
#16
Larry,

I thought it might be that some stocks, already open, got re-signalled for March 2023. So, I tried a test with the NASDAQ 100, and NFLX and MELI did not resignal for March 2023.

Can you post your strategy settings?
0
- ago
#17
Paul,

Here is the Strategy Settings for the above strategy.

Thank you for your help.

Larry

0
- ago
#18
NFLX and MELI are re-signalled. That's why they're not getting closed. I didn't check PDD. Here's code you can substitute for the foreach loop that goes through the OpenPositionsAllSymbols. For the latest month, the buys list has NFLX and MELI in it, meaning they got re-signalled. The debugging code below is very specific to NFLX and MELI, otherwise the debug log gets flooded...

CODE:
foreach (var pos in OpenPositionsAllSymbols) { if (!buys.Contains(pos.Bars)) { // find the relevant bar for the given current date var idx = pos.Bars.IndexOf(dt, true); if (idx >= 0 && pos.Bars.DateTimes[idx].IsLastTradingDayOfMonth(pos.Bars)) { ClosePosition(pos, OrderType.Market); if ((pos.Symbol == "NFLX" || pos.Symbol == "MELI") && dt >= new DateTime(2023, 2, 1)) { WriteToDebugLog($"Closed {pos.Symbol} on {dt}"); } } } else if ((pos.Symbol == "NFLX" || pos.Symbol == "MELI") && dt >= new DateTime(2023, 2, 1)) { WriteToDebugLog($"{pos.Symbol} carried forward at {dt}"); } }
0
- ago
#19
Paul,

Very interesting.
Did not think of this as a re-signal.
Much appreciated.

- Larry
0

Reply

Bookmark

Sort