Glitch8
 ( 11.87% )
- ago
Here is the C# Code for the Correspinding Trading War Room Youtube video just published!

Link to Video:
https://youtu.be/uKu3I04mwZ0

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using System.Drawing; using System.Collections.Generic; using System.Linq; namespace WealthScript1 {    public class MyStrategy : UserStrategyBase    {       //Initialize - create Returns Trackers to log percentage returns after certain intervals       public override void Initialize(BarHistory bars)       {          for (int mState = 0; mState < 4; mState++)          {             _returnTrackers[mState] = new List<ReturnsTracker>();             foreach (int period in _nBarPeriods)             {                ReturnsTracker rt = new ReturnsTracker(bars, period);                _returnTrackers[mState].Add(rt);             }          }       }       //Execute       public override void Execute(BarHistory bars, int idx)       {          //track high, low closes, pullbacks          double c = bars.Close[idx];          if (c > _highestClose)             _highestClose = c;          if (c < _lowestClose)             _lowestClose = c;          double bullPullback = (_highestClose - c) * 100.0 / _highestClose;          double bearPullback = (c - _lowestClose) * 100.0 / _lowestClose;          //make calculates and counts based on current market state          switch (_marketState)          {             case MarketState.Undefined:                if (bullPullback >= 20.0)                   BeginBearMarket(idx, c);                else if (bearPullback >= 20.0)                   BeginBullMarket(idx, c);                break;             case MarketState.Bull:             case MarketState.BullCorrection:                if (bullPullback >= 20.0)                   BeginBearMarket(idx, c);                else if (bullPullback >= 10.0)                {                   if (_marketState == MarketState.Bull)                      _bullCorrs++;                   _marketState = MarketState.BullCorrection;                }                else                   _marketState = MarketState.Bull;                break;             case MarketState.Bear:             case MarketState.BearCorrection:                if (bearPullback >= 20.0)                   BeginBullMarket(idx, c);                else if (bearPullback >= 10.0)                {                   if (_marketState == MarketState.Bear)                      _bearCorrs++;                   _marketState = MarketState.BearCorrection;                }                else                   _marketState = MarketState.Bear;                break;          }          //color chart based on market state          Color color = Color.Transparent;          switch (_marketState)          {             case MarketState.BullCorrection:                color = Color.FromArgb(32, 128, 255, 128);                break;             case MarketState.Bull:                color = Color.FromArgb(64, 0, 255, 0);                break;             case MarketState.BearCorrection:                color = Color.FromArgb(32, 255, 128, 128);                break;             case MarketState.Bear:                color = Color.FromArgb(64, 255, 0, 0);                break;          }          SetBackgroundColor(bars, idx, color);          //Log N-Bar returns for the current state          if (_marketState != MarketState.Undefined)          {             int mState = (int)_marketState;             List<ReturnsTracker> lst = _returnTrackers[mState];             foreach(ReturnsTracker rt in lst)                rt.CalcReturns(idx);          }       }       //output       public override void Cleanup(BarHistory bars)       {          //record length of current state          if (_startIdx > -1)          {             int length = bars.Count - 1 - _startIdx;             if (_marketState == MarketState.Bull || _marketState == MarketState.BullCorrection)                _bullLengths.Add(length);             else                _bearLengths.Add(length);          }          //show current state on chart          DrawHeaderText("Market State is: " + _marketState, Color.Black, 12);          //debug log          WriteToDebugLog("Bull Markets: " + _bulls);          if (_bullLengths.Count > 0)             WriteToDebugLog("Average Length: " + _bullLengths.Average().ToString("N2"));          WriteToDebugLog("Corrections: " + _bullCorrs);          if (_bullCorrs > 0)             WriteToDebugLog("Chance of Correction -> Bear Market: " + (_bears * 100.0 / _bullCorrs).ToString("N2") + "%");          WriteToDebugLog("");          WriteToDebugLog("Bear Markets: " + _bears);          if (_bearLengths.Count > 0)             WriteToDebugLog("Average Length: " + _bearLengths.Average().ToString("N2"));          WriteToDebugLog("Corrections: " + _bearCorrs);          if (_bullCorrs > 0)             WriteToDebugLog("Chance of Correction -> Bull Market: " + (_bulls * 100.0 / _bearCorrs).ToString("N2") + "%");          //report N-Bar Returns for each State          WriteToDebugLog("");          WriteToDebugLog("N-Bar Returns by Market State");          string header = "\t\t\tday\tweek\tmnth\t3m\t6m\t1y";          WriteToDebugLog(header);          for (int mState = 0; mState < 4; mState++)          {             MarketState ms = (MarketState)mState;             string line = ms.ToString();             if (line.Length == 4)                line += " ";             line += "\t";             List<ReturnsTracker> lst = _returnTrackers[mState];             foreach(ReturnsTracker rt in lst)                line += rt.AvgReturn.ToString("N2") + "\t";             WriteToDebugLog(line);          }       }       //private members       private MarketState _marketState = MarketState.Undefined;       private double _highestClose = Double.MinValue;       private double _lowestClose = Double.MaxValue;       private int _bears, _bulls = 0;       private int _bearCorrs, _bullCorrs = 0;       private int _startIdx = -1;       private List<int> _bullLengths = new List<int>();       private List<int> _bearLengths = new List<int>();       private List<ReturnsTracker>[] _returnTrackers = new List<ReturnsTracker>[4];       private List<int> _nBarPeriods = new List<int> { 1, 5, 252 / 12, 252 / 4, 252 / 2, 252 };       //begin a bull market       private void BeginBullMarket(int idx, double price)       {          _marketState = MarketState.Bull;          _highestClose = price;          _bulls++;          if (_startIdx > -1)          {             int length = idx - _startIdx;             _bearLengths.Add(length);          }          _startIdx = idx;       }       //begin a bear market       private void BeginBearMarket(int idx, double price)       {          _marketState = MarketState.Bear;          _lowestClose = price;          _bears++;          if (_startIdx > -1)          {             int length = idx - _startIdx;             _bullLengths.Add(length);          }          _startIdx = idx;       }    }    //an enum to track market state    public enum MarketState { Bull, BullCorrection, Bear, BearCorrection, Undefined };    //This class is used to track market returns after N-Bars    public class ReturnsTracker    {       //constructor       public ReturnsTracker(BarHistory bars, int numBars)       {          _bars = bars;          NBars = numBars;       }              //Number of bars       public int NBars { get; set; }       //Observations       public double Observations { get; set; } = 0.0;       //Sum Returns       public double SumReturns { get; set; } = 0.0;       //Avg Return       public double AvgReturn => Observations == 0 ? 0.0 : SumReturns / Observations;       //log the returns       public void CalcReturns(int idx)       {          int endIdx = idx + NBars;          if (endIdx < _bars.Count)          {             double gain = _bars.Close[endIdx] - _bars.Close[idx];             gain = gain * 100.0 / _bars.Close[idx];             Observations++;             SumReturns += gain;          }       }       //private members       private BarHistory _bars;    } }
3
1,684
12 Replies

Reply

Bookmark

Sort
Glitch8
 ( 11.87% )
- ago
#1
I just updated the code above with the inclusion of an average N-Bar returns tracking mechanism. It's interesting to see the average returns over different periods for each of the 4 defined market states, and the ability to run this on any index (or any asset) is very nice!

Watch for a new video describing these changes soon. A next step I might take is trying to identity profitable intraday strategies for each of the larger market states - stay tuned!

Here's my output for the Nasdaq Composite, for example:

CODE:
---Symbol by Symbol Debug Logs--- ---$COMP--- Bull Markets: 18 Average Length: 596.44 Corrections: 133 Chance of Correction -> Bear Market: 12.78% Bear Markets: 17 Average Length: 109.71 Corrections: 60 Chance of Correction -> Bull Market: 30.00% N-Bar Returns by Market State        day    week   mnth   3m    6m    1y Bull    0.06   0.29   1.09   3.00   6.26   12.67    BullCorrection   -0.00 0.10   1.10   4.94   8.80   12.65    Bear    -0.02 -0.11 0.19   1.03   2.42   12.60    BearCorrection   0.08   0.40   1.02   4.61   8.69   18.08   
3
- ago
#2
This is an awesome indicator. Can you please create an indicator that we can use in our strategy, such as market state indicator or bullmarket , bear market etc.
0
Glitch8
 ( 11.87% )
- ago
#3
Yes, was already considering that! It’s funny, but so far I haven’t seen an indicator like this that just uses the classic definition to establish the market state.
0
- ago
#4
Okay, I'm using ^IXIC (for the NASDAQ composite) over 800 bars. What adjustments do I need to do to get your numbers?

CODE:
---Symbol by Symbol Debug Logs--- ---^IXIC--- Bull Markets: 2 Average Length: 358.50 Corrections: 9 Chance of Correction -> Bear Market: 11.11% Bear Markets: 1 Average Length: 22.00 Corrections: 3 Chance of Correction -> Bull Market: 66.67% N-Bar Returns by Market State          day   week   mnth   3m   6m   1y Bull    0.07   0.44   1.88   5.85   13.31   32.55    BullCorrection   -0.04   -2.19   -0.54   15.75   29.58   48.17    Bear    1.51   3.99   17.58   37.00   51.23   83.69    BearCorrection   -0.21   3.79   12.90   29.66   41.29   71.15   
0
Glitch8
 ( 11.87% )
- ago
#5
Looks like you need a larger data range.
1
Glitch8
 ( 11.87% )
- ago
#6
Second part of the video featuring this Strategy has just been pushed ...

https://youtu.be/iGojKvwOoDw
0
- ago
#7
Thanks for that video. Very interesting conclusions from that summary table.

I did rework the formatting for that summary table so the decimals would line up.

CODE:
         //report N-Bar Returns for each State          WriteToDebugLog("\nN-Bar Returns by Market State");          WriteToDebugLog("\t\t\tday\tweek\tmnth\t3mo\t6mo\t1yr");          for (int mState = 0; mState < 4; mState++)          {             MarketState ms = (MarketState)mState;             string line = String.Format("{0,17}",ms);             List<ReturnsTracker> lst = _returnTrackers[mState];             foreach(ReturnsTracker rt in lst)                line += String.Format("{0,7:N2}",rt.AvgReturn);             WriteToDebugLog(line);          }
0
- ago
#8
Here is a revamp of the code so that it works in WealthLab 8. I also implemented superticker's reworked format for the summary table:

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using System.Drawing; using System.Collections.Generic; using System.Linq; namespace WealthScript1 {    public class MyStrategy : UserStrategyBase    {       //Initialize - create Returns Trackers to log percentage returns after certain intervals       public override void Initialize(BarHistory bars)       {          for (int mState = 0; mState < 4; mState++)          {             _returnTrackers[mState] = new List<ReturnsTracker>();             foreach (int period in _nBarPeriods)             {                ReturnsTracker rt = new ReturnsTracker(bars, period);                _returnTrackers[mState].Add(rt);             }          }       }       //Execute       public override void Execute(BarHistory bars, int idx)       {          //track high, low closes, pullbacks          double c = bars.Close[idx];          if (c > _highestClose)             _highestClose = c;          if (c < _lowestClose)             _lowestClose = c;          double bullPullback = (_highestClose - c) * 100.0 / _highestClose;          double bearPullback = (c - _lowestClose) * 100.0 / _lowestClose;          //make calculates and counts based on current market state          switch (_marketState)          {             case MarketState.Undefined:                if (bullPullback >= 20.0)                   BeginBearMarket(idx, c);                else if (bearPullback >= 20.0)                   BeginBullMarket(idx, c);                break;             case MarketState.Bull:             case MarketState.BullCorrection:                if (bullPullback >= 20.0)                   BeginBearMarket(idx, c);                else if (bullPullback >= 10.0)                {                   if (_marketState == MarketState.Bull)                      _bullCorrs++;                   _marketState = MarketState.BullCorrection;                }                else                   _marketState = MarketState.Bull;                break;             case MarketState.Bear:             case MarketState.BearCorrection:                if (bearPullback >= 20.0)                   BeginBullMarket(idx, c);                else if (bearPullback >= 10.0)                {                   if (_marketState == MarketState.Bear)                      _bearCorrs++;                   _marketState = MarketState.BearCorrection;                }                else                   _marketState = MarketState.Bear;                break;          }          //color chart based on market state          WLColor color = WLColor.Transparent;          switch (_marketState)          {             case MarketState.BullCorrection:                color = WLColor.FromArgb(32, 128, 255, 128);                break;             case MarketState.Bull:                color = WLColor.FromArgb(64, 0, 255, 0);                break;             case MarketState.BearCorrection:                color = WLColor.FromArgb(32, 255, 128, 128);                break;             case MarketState.Bear:                color = WLColor.FromArgb(64, 255, 0, 0);                break;          }          SetBackgroundColor(bars, idx, color);          //Log N-Bar returns for the current state          if (_marketState != MarketState.Undefined)          {             int mState = (int)_marketState;             List<ReturnsTracker> lst = _returnTrackers[mState];             foreach(ReturnsTracker rt in lst)                rt.CalcReturns(idx);          }       }       //output       public override void Cleanup(BarHistory bars)       {          //record length of current state          if (_startIdx > -1)          {             int length = bars.Count - 1 - _startIdx;             if (_marketState == MarketState.Bull || _marketState == MarketState.BullCorrection)                _bullLengths.Add(length);             else                _bearLengths.Add(length);          }          //show current state on chart          DrawHeaderText("Market State is: " + _marketState, WLColor.Black, 12);          //debug log          WriteToDebugLog("Bull Markets: " + _bulls);          if (_bullLengths.Count > 0)             WriteToDebugLog("Average Length: " + _bullLengths.Average().ToString("N2"));          WriteToDebugLog("Corrections: " + _bullCorrs);          if (_bullCorrs > 0)             WriteToDebugLog("Chance of Correction -> Bear Market: " + (_bears * 100.0 / _bullCorrs).ToString("N2") + "%");          WriteToDebugLog("");          WriteToDebugLog("Bear Markets: " + _bears);          if (_bearLengths.Count > 0)             WriteToDebugLog("Average Length: " + _bearLengths.Average().ToString("N2"));          WriteToDebugLog("Corrections: " + _bearCorrs);          if (_bullCorrs > 0)             WriteToDebugLog("Chance of Correction -> Bull Market: " + (_bulls * 100.0 / _bearCorrs).ToString("N2") + "%");          //report N-Bar Returns for each State          WriteToDebugLog("\nN-Bar Returns by Market State");          WriteToDebugLog("\t\t\tday\tweek\tmnth\t3mo\t6mo\t1yr");          for (int mState = 0; mState < 4; mState++)          {             MarketState ms = (MarketState)mState;             string line = String.Format("{0,17}", ms);             List<ReturnsTracker> lst = _returnTrackers[mState];             foreach(ReturnsTracker rt in lst)                line += String.Format("{0,7:N2}", rt.AvgReturn);             WriteToDebugLog(line);          }       }       //private members       private MarketState _marketState = MarketState.Undefined;       private double _highestClose = Double.MinValue;       private double _lowestClose = Double.MaxValue;       private int _bears, _bulls = 0;       private int _bearCorrs, _bullCorrs = 0;       private int _startIdx = -1;       private List<int> _bullLengths = new List<int>();       private List<int> _bearLengths = new List<int>();       private List<ReturnsTracker>[] _returnTrackers = new List<ReturnsTracker>[4];       private List<int> _nBarPeriods = new List<int> { 1, 5, 252 / 12, 252 / 4, 252 / 2, 252 };       //begin a bull market       private void BeginBullMarket(int idx, double price)       {          _marketState = MarketState.Bull;          _highestClose = price;          _bulls++;          if (_startIdx > -1)          {             int length = idx - _startIdx;             _bearLengths.Add(length);          }          _startIdx = idx;       }       //begin a bear market       private void BeginBearMarket(int idx, double price)       {          _marketState = MarketState.Bear;          _lowestClose = price;          _bears++;          if (_startIdx > -1)          {             int length = idx - _startIdx;             _bullLengths.Add(length);          }          _startIdx = idx;       }    }    //an enum to track market state    public enum MarketState { Bull, BullCorrection, Bear, BearCorrection, Undefined };    //This class is used to track market returns after N-Bars    public class ReturnsTracker    {       //constructor       public ReturnsTracker(BarHistory bars, int numBars)       {          _bars = bars;          NBars = numBars;       }       //Number of bars       public int NBars { get; set; }       //Observations       public double Observations { get; set; } = 0.0;       //Sum Returns       public double SumReturns { get; set; } = 0.0;       //Avg Return       public double AvgReturn => Observations == 0 ? 0.0 : SumReturns / Observations;       //log the returns       public void CalcReturns(int idx)       {          int endIdx = idx + NBars;          if (endIdx < _bars.Count)          {             double gain = _bars.Close[endIdx] - _bars.Close[idx];             gain = gain * 100.0 / _bars.Close[idx];             Observations++;             SumReturns += gain;          }       }       //private members       private BarHistory _bars;    } }

3
- ago
#9
What would be really interesting is to add some columns for WL's IndexLab market sentiment oscillators such as CompMcClellen or CompTRIN. I would like to see how well these composite oscillators correlate with the BullBear results.

For market sentiment trading, I would probably use one of these composite oscillators to steer my trading. But I would like to pick the oscillator that follows the BullBear results as much as possible.
0
- ago
#10
Why not simply use the CNN Fear & Greed data to mesure market state? I'm holding data going back to January 2011, so I could export it out of MongoDB but it would have to be maintained by the Wealth-Lab team.

Fear & Greed Data can be downloaded via https://production.dataviz.cnn.io/index/fearandgreed/graphdata. Simply feed the http-header in such a way that the endpoint believes that a real browser is coming along.
0
Glitch8
 ( 11.87% )
- ago
#11
I’ve been looking for a historical source of the Fear and Greed for ages, where did you find that link?

I’ll get this packaged as a PowerPack indicator.

It’ll be great to have, but it’s a sentiment indicator and not a replacement for the classic market state indicator which is based on price movement alone.
0
Glitch8
 ( 11.87% )
- ago
#12
Let's resume this new discussion in a new topic, I'll create a CNN Fear/Greed topic.
0

Reply

Bookmark

Sort