|
| 1 | +package momentum |
| 2 | + |
| 3 | +import ( |
| 4 | + "github.com/cinar/indicator/v2/helper" |
| 5 | + "github.com/cinar/indicator/v2/trend" |
| 6 | +) |
| 7 | + |
| 8 | +// PringsSpecialK implements Martin Pring's Special K momentum indicator. |
| 9 | +// It composes multiple Rate-of-Change (ROC) series smoothed by Simple Moving Averages (SMA) |
| 10 | +// and outputs a weighted sum aligned to the slowest path so all terms are time-synchronized. |
| 11 | +// See Compute for the exact composition and weights. |
| 12 | +type PringsSpecialK[T helper.Float] struct { |
| 13 | + Roc10 *trend.Roc[T] |
| 14 | + Roc15 *trend.Roc[T] |
| 15 | + Roc20 *trend.Roc[T] |
| 16 | + Roc30 *trend.Roc[T] |
| 17 | + Roc40 *trend.Roc[T] |
| 18 | + Roc65 *trend.Roc[T] |
| 19 | + Roc75 *trend.Roc[T] |
| 20 | + Roc100 *trend.Roc[T] |
| 21 | + Roc195 *trend.Roc[T] |
| 22 | + Roc265 *trend.Roc[T] |
| 23 | + Roc390 *trend.Roc[T] |
| 24 | + Roc530 *trend.Roc[T] |
| 25 | + |
| 26 | + Sma10Roc10 *trend.Sma[T] |
| 27 | + Sma10Roc15 *trend.Sma[T] |
| 28 | + Sma10Roc20 *trend.Sma[T] |
| 29 | + Sma15Roc30 *trend.Sma[T] |
| 30 | + Sma50Roc40 *trend.Sma[T] |
| 31 | + Sma65Roc65 *trend.Sma[T] |
| 32 | + Sma75Roc75 *trend.Sma[T] |
| 33 | + Sma100Roc100 *trend.Sma[T] |
| 34 | + Sma130Roc195 *trend.Sma[T] |
| 35 | + Sma130Roc265 *trend.Sma[T] |
| 36 | + Sma130Roc390 *trend.Sma[T] |
| 37 | + Sma195Roc530 *trend.Sma[T] |
| 38 | +} |
| 39 | + |
| 40 | +// NewPringsSpecialK function initializes a new Martin Pring's Special K instance. |
| 41 | +func NewPringsSpecialK[T helper.Float]() *PringsSpecialK[T] { |
| 42 | + return &PringsSpecialK[T]{ |
| 43 | + Roc10: trend.NewRocWithPeriod[T](10), |
| 44 | + Roc15: trend.NewRocWithPeriod[T](15), |
| 45 | + Roc20: trend.NewRocWithPeriod[T](20), |
| 46 | + Roc30: trend.NewRocWithPeriod[T](30), |
| 47 | + Roc40: trend.NewRocWithPeriod[T](40), |
| 48 | + Roc65: trend.NewRocWithPeriod[T](65), |
| 49 | + Roc75: trend.NewRocWithPeriod[T](75), |
| 50 | + Roc100: trend.NewRocWithPeriod[T](100), |
| 51 | + Roc195: trend.NewRocWithPeriod[T](195), |
| 52 | + Roc265: trend.NewRocWithPeriod[T](265), |
| 53 | + Roc390: trend.NewRocWithPeriod[T](390), |
| 54 | + Roc530: trend.NewRocWithPeriod[T](530), |
| 55 | + |
| 56 | + Sma10Roc10: trend.NewSmaWithPeriod[T](10), |
| 57 | + Sma10Roc15: trend.NewSmaWithPeriod[T](10), |
| 58 | + Sma10Roc20: trend.NewSmaWithPeriod[T](10), |
| 59 | + Sma15Roc30: trend.NewSmaWithPeriod[T](15), |
| 60 | + Sma50Roc40: trend.NewSmaWithPeriod[T](50), |
| 61 | + Sma65Roc65: trend.NewSmaWithPeriod[T](65), |
| 62 | + Sma75Roc75: trend.NewSmaWithPeriod[T](75), |
| 63 | + Sma100Roc100: trend.NewSmaWithPeriod[T](100), |
| 64 | + Sma130Roc195: trend.NewSmaWithPeriod[T](130), |
| 65 | + Sma130Roc265: trend.NewSmaWithPeriod[T](130), |
| 66 | + Sma130Roc390: trend.NewSmaWithPeriod[T](130), |
| 67 | + Sma195Roc530: trend.NewSmaWithPeriod[T](195), |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +func (p *PringsSpecialK[T]) Compute(closings <-chan T) <-chan T { |
| 72 | + c := helper.Duplicate(closings, 12) |
| 73 | + |
| 74 | + roc10 := p.Roc10.Compute(c[0]) |
| 75 | + roc15 := p.Roc15.Compute(c[1]) |
| 76 | + roc20 := p.Roc20.Compute(c[2]) |
| 77 | + roc30 := p.Roc30.Compute(c[3]) |
| 78 | + roc40 := p.Roc40.Compute(c[4]) |
| 79 | + roc65 := p.Roc65.Compute(c[5]) |
| 80 | + roc75 := p.Roc75.Compute(c[6]) |
| 81 | + roc100 := p.Roc100.Compute(c[7]) |
| 82 | + roc195 := p.Roc195.Compute(c[8]) |
| 83 | + roc265 := p.Roc265.Compute(c[9]) |
| 84 | + roc390 := p.Roc390.Compute(c[10]) |
| 85 | + roc530 := p.Roc530.Compute(c[11]) |
| 86 | + |
| 87 | + sma10Roc10 := p.Sma10Roc10.Compute(roc10) |
| 88 | + sma10Roc15 := p.Sma10Roc15.Compute(roc15) |
| 89 | + sma10Roc20 := p.Sma10Roc20.Compute(roc20) |
| 90 | + sma15Roc30 := p.Sma15Roc30.Compute(roc30) |
| 91 | + sma50Roc40 := p.Sma50Roc40.Compute(roc40) |
| 92 | + sma65Roc65 := p.Sma65Roc65.Compute(roc65) |
| 93 | + sma75Roc75 := p.Sma75Roc75.Compute(roc75) |
| 94 | + sma100Roc100 := p.Sma100Roc100.Compute(roc100) |
| 95 | + sma130Roc195 := p.Sma130Roc195.Compute(roc195) |
| 96 | + sma130Roc265 := p.Sma130Roc265.Compute(roc265) |
| 97 | + sma130Roc390 := p.Sma130Roc390.Compute(roc390) |
| 98 | + sma195Roc530 := p.Sma195Roc530.Compute(roc530) |
| 99 | + |
| 100 | + maxIdle := p.Sma195Roc530.IdlePeriod() + p.Roc530.IdlePeriod() |
| 101 | + |
| 102 | + sma10Roc10 = helper.Skip(sma10Roc10, maxIdle-p.Sma10Roc10.IdlePeriod()-p.Roc10.IdlePeriod()) |
| 103 | + sma10Roc15 = helper.Skip(sma10Roc15, maxIdle-p.Sma10Roc15.IdlePeriod()-p.Roc15.IdlePeriod()) |
| 104 | + sma10Roc20 = helper.Skip(sma10Roc20, maxIdle-p.Sma10Roc20.IdlePeriod()-p.Roc20.IdlePeriod()) |
| 105 | + sma15Roc30 = helper.Skip(sma15Roc30, maxIdle-p.Sma15Roc30.IdlePeriod()-p.Roc30.IdlePeriod()) |
| 106 | + sma50Roc40 = helper.Skip(sma50Roc40, maxIdle-p.Sma50Roc40.IdlePeriod()-p.Roc40.IdlePeriod()) |
| 107 | + sma65Roc65 = helper.Skip(sma65Roc65, maxIdle-p.Sma65Roc65.IdlePeriod()-p.Roc65.IdlePeriod()) |
| 108 | + sma75Roc75 = helper.Skip(sma75Roc75, maxIdle-p.Sma75Roc75.IdlePeriod()-p.Roc75.IdlePeriod()) |
| 109 | + sma100Roc100 = helper.Skip(sma100Roc100, maxIdle-p.Sma100Roc100.IdlePeriod()-p.Roc100.IdlePeriod()) |
| 110 | + sma130Roc195 = helper.Skip(sma130Roc195, maxIdle-p.Sma130Roc195.IdlePeriod()-p.Roc195.IdlePeriod()) |
| 111 | + sma130Roc265 = helper.Skip(sma130Roc265, maxIdle-p.Sma130Roc265.IdlePeriod()-p.Roc265.IdlePeriod()) |
| 112 | + sma130Roc390 = helper.Skip(sma130Roc390, maxIdle-p.Sma130Roc390.IdlePeriod()-p.Roc390.IdlePeriod()) |
| 113 | + |
| 114 | + p0 := helper.MultiplyBy(sma10Roc10, 1) |
| 115 | + p1 := helper.Add(p0, helper.MultiplyBy(sma10Roc15, 2)) |
| 116 | + p2 := helper.Add(p1, helper.MultiplyBy(sma10Roc20, 3)) |
| 117 | + p3 := helper.Add(p2, helper.MultiplyBy(sma15Roc30, 4)) |
| 118 | + p4 := helper.Add(p3, helper.MultiplyBy(sma50Roc40, 1)) |
| 119 | + p5 := helper.Add(p4, helper.MultiplyBy(sma65Roc65, 2)) |
| 120 | + p6 := helper.Add(p5, helper.MultiplyBy(sma75Roc75, 3)) |
| 121 | + p7 := helper.Add(p6, helper.MultiplyBy(sma100Roc100, 4)) |
| 122 | + p8 := helper.Add(p7, helper.MultiplyBy(sma130Roc195, 1)) |
| 123 | + p9 := helper.Add(p8, helper.MultiplyBy(sma130Roc265, 2)) |
| 124 | + p10 := helper.Add(p9, helper.MultiplyBy(sma130Roc390, 3)) |
| 125 | + p11 := helper.Add(p10, helper.MultiplyBy(sma195Roc530, 4)) |
| 126 | + |
| 127 | + return p11 |
| 128 | +} |
0 commit comments