Henk8
- ago
Hi,

I 'm a big supporter of bollinger bands. My intention is to bring all the bollinger bands followers of WL together and discourse on the strategies. If it interests you guys let me know. Reply with Yes, Ja, Oui, Si etc.
1
907
11 Replies

Reply

Bookmark

Sort
Henk8
- ago
#1
I asked to chatGpt what's the best strategy and it was the squeeze.
0
Henk8
- ago
#2
https://www.wealth-lab.com/Discussion/How-to-create-Bollinger-Band-Squeeze-strategy-5577
0
- ago
#3
QUOTE:
... asked ChatGPT what's the best strategy and it was the squeeze.

I think ChatGPT was referring to John Carter's "squeeze strategy", which made him famous. And that strategy employs both Keltner Bands as well as Bollinger Bands. The problem is the John Carter squeeze is a rare occurrence.

UPDATE: The code below captures John Carter's method. I did switch to a DSMA integrator to improve the results, but if one changes the strategy too much, one can't call it John Carter's squeeze method anymore. I also added optimization parameters to improve the exit timing. Post symbol-by-symbol optimization with the SMAC optimizer, for all failing cases, the failure is at the end of the squeeze period when the strategy makes its hail Mary decision on whether to go Long or Short. How best to do that is up for discussion. You should employ the code below as starting material for crafting your own improved method; make John Carter proud.

CODE:
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; using WealthLab.TASC; namespace WealthScript1 {    public class SqueezeStrategy : UserStrategyBase    {       //John F Carter's "Squeeze" strategy from his book "Mastering the Trade"       //converted from WL6: ActiveTrader 2009-02 | Double-band squeeze system       public SqueezeStrategy()       {          dsmaPeriod = AddParameter("DSMA period", ParameterType.Int32, 12, 5, 25);          barsXitThreshold = AddParameter("#bars Xit threshold", ParameterType.Double, 1.0, 1.0, 5.0);       }       const int period = 20;       public override void Initialize(BarHistory bars)       {          bbU = BBUpper.Series(bars.Close, period, 2.0);          bbL = BBLower.Series(bars.Close, period, 2.0);          kU = KeltnerUpper.Series(bars, period, default, period);          kL = KeltnerLower.Series(bars, period, default, period);          PlotIndicatorBands(bbU, bbL, WLColor.DodgerBlue.SetAlpha(120), 1, 20);          PlotIndicatorBands(kU, kL, WLColor.Aqua, 0, 25);          momentum = new Momentum(bars.Close, 1);          smoothedMomentum = new DSMA(momentum, dsmaPeriod.AsInt);          smoothedMomentum.Description = "Smoothed momentum oscillator";          PlotIndicatorHistogramTwoColor(smoothedMomentum);          DrawHorzLine(0.0,WLColor.Red,1,LineStyle.Dashed,"smoothedMomentum");          squeeze = new Squeeze(bars, bars.Close, period, 2.0);          PlotIndicator(squeeze,WLColor.Blue, PlotStyle.Histogram);          barsMomentumFalls = new ConsecDown(smoothedMomentum, 1);          barsMomentumFalls.Description = "Consecutive bars momentum falls";          barsMomentumRises = new ConsecUp(smoothedMomentum, 1);          barsMomentumRises.Description = "Consecutive bars momentum rises";          StartIndex = squeeze.FirstValidIndex;       }       int sqzStartIdx = -1; //reset squeeze start index       public override void Execute(BarHistory bars, int idx)       {          SetSeriesBarColor(smoothedMomentum,idx,smoothedMomentum[idx]>=0 ? WLColor.SeaGreen : WLColor.DeepPink);          if (HasOpenPosition(bars, PositionType.Long))          {             //sell Long positions here             if (barsMomentumFalls[idx] >= barsXitThreshold.AsDouble)                PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0.0, barsMomentumFalls[idx].ToString("#=barsMomentFall Long Xit"));          }          else if (HasOpenPosition(bars, PositionType.Short))          {             //sell (cover) Short positions here             if (barsMomentumRises[idx] >= barsXitThreshold.AsDouble)                PlaceTrade(bars, TransactionType.Cover, OrderType.Market, 0.0, barsMomentumRises[idx].ToString("#=barsMomentRise Shrt Xit"));          }          else          {   /* Squeeze tracking */             if (sqzStartIdx<0) //No squeeze currently in progress?             {                if (squeeze[idx] < 0.0) //Is squeeze beginning?                   sqzStartIdx = idx; //yes, squeeze is starting             }             if (sqzStartIdx>0) //Is squeeze underway?             {                SetBackgroundColorAllPanes(bars, idx, WLColor.Gold.SetAlpha(90)); //color bars during squeeze                                if (squeeze[idx] > 0.0) //Is squeeze just over? If so, perform post-squeeze trades                {                   if (smoothedMomentum[idx] > 0.0) //Is momentum positive?                   { //yes, buy long                      SetBackgroundColor(bars, idx+1, WLColor.Green.SetAlpha(150));                      Transaction t = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0.0, (idx-sqzStartIdx+1).ToString("0#=sqzSpan Long buy"));                      t.Weight = smoothedMomentum[idx];                   }                   else                   { //no, buy short                      SetBackgroundColor(bars, idx+1, WLColor.Orange.SetAlpha(150));                      Transaction t = PlaceTrade(bars, TransactionType.Short, OrderType.Market, 0.0, (idx-sqzStartIdx+1).ToString("0#=sqzSpan Short buy"));                      t.Weight = -smoothedMomentum[idx];                   }                   sqzStartIdx = -1; //squeeze over; reset sqzStartIdx                }             }          }       }       Parameter dsmaPeriod, barsXitThreshold;       IndicatorBase bbU, bbL, kU, kL, momentum, smoothedMomentum, squeeze;       IndicatorBase barsMomentumFalls, barsMomentumRises;    } }

Please don't ask how to express this in blocks. That's a really scary thought.
2
Henk8
- ago
#4
Thanks Superticker.
0
- ago
#5
I just posted an update to the above code that you can employ symbol-by-symbol optimization using the SMAC optimizer; I optimize for maximum profit.

Do post your code improvements for this strategy. I would be interested.
0
ww58
- ago
#6
@superticker, what APR do you get using this strategy? I have a loss for each year testing on the S&P 100 daily set, but the entry points are good, which gives a chance for further improvement
0
- ago
#7
QUOTE:
what APR do you get using this strategy?

When testing against the Dow 30, I get 18%, see below. When using it with my proprietary indicators, I get about 20%.



But it has issues. Looking at the By Symbol results listing, there's either a 100% win rate or a very poor win rate. When it does its hail Mary to pick whether to go Long or Short following the end of the squeeze, it can get this wrong. Once it gets it wrong, it's too slow to get out. It should give up and exit immediately when it gets it wrong.

I do think the exit criteria could be improved. For one, it doesn't use an indicator that tracks volume for exiting, which is a big shortcoming. I really haven't looked at it much in great detail. I'm just trying to illustrate John Carter's approach here. But remember, the devil is in the details. The production version of this will be more complicated.
1
ww58
- ago
#8
I got a completely different result, I'm still figuring it out

0
- ago
#9
You need to be using Symbol-by-Symbol optimization, not Standard optimization, with the SMAC optimizer. That's because the exiting parameters will be different for each stock. Also, picking 1.0 as the default value for the #bars Xit threshold was a bad choice; that's now changed to 4.0.
CODE:
barsXitThreshold = AddParameter("#bars Xit threshold", ParameterType.Double, 4.0, 1.0, 6.0);
I would also allow for at least five or six positions to be held by the strategy before running out of funds for the Dow 30.

1
- ago
#10
Tried a lot with BB in all those years. Mixed fan.

I give it another try, using BB stoch.
See
https://www.wealth-lab.com/Discussion/Bollinger-Stochastic-as-new-indicator-10376
0
- ago
#11
QUOTE:
I'll give it another try, using BB stochastic.

Well, the point behind John Carter's Bollinger Bands is to wait for a squeeze (i.e. sustained reduction in the standard deviation of the price), then do a Buy immediately following the squeeze (jump in the standard deviation). The BB stochastic bands effectively flattens out the changes in the standard deviation making it even more difficult to gauge when the squeeze starts and ends. That said, I'm thinking using BB stochastic bands would make this strategy worse. But if you can prove me wrong, please post your solution.

I think the no-brainer way to improve the squeeze strategy in Reply# 3 is to introduce some ATR training stop exits into it, but I haven't tried it. The Reply# 3 code relies on momentum changes for the exit with the threshold set by the optimizer. Unfortunately, the optimizer isn't dynamic enough to get it right over time. One needs to employ a more adaptive indicator that includes Volume action as well for the exit.
0

Reply

Bookmark

Sort