feat(overlap): add advanced overlap studies wrappers and wire TA-Lib symbols
- add TA-Lib function pointer signatures in functions.go for: MA, MAMA, MAVP, MIDPOINT, MIDPRICE, SAR, SAREXT, SMA, T3, TEMA, TRIMA, WMA - register new symbols in Load() via purego.RegisterLibFunc in loader.go - add public overlap study wrappers in overlap_studies.go with consistent nil-on-failure behavior - update README overlap studies list to match implemented API
This commit is contained in:
@@ -31,7 +31,7 @@ This project currently exposes a focused subset of TA-Lib functions:
|
|||||||
- Stochastic family: `Stoch`, `StochF`, `StochRSI`
|
- Stochastic family: `Stoch`, `StochF`, `StochRSI`
|
||||||
|
|
||||||
**Overlap Studies**
|
**Overlap Studies**
|
||||||
- `AccBands`, `BBands`, `DEMA`, `EMA`, `HT_TRENDLINE`, `KAMA`
|
- `AccBands`, `BBands`, `DEMA`, `EMA`, `HT_TRENDLINE`, `KAMA`, `MA`, `MAMA`, `MAVP`, `MidPoint`, `MidPrice`, `SAR`, `SARExt`, `SMA`, `T3`, `TEMA`, `TRIMA`, `WMA`
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|||||||
+138
@@ -738,4 +738,142 @@ var (
|
|||||||
outNBElement *int32,
|
outNBElement *int32,
|
||||||
outReal []float64,
|
outReal []float64,
|
||||||
) int32
|
) int32
|
||||||
|
|
||||||
|
ma func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
optInMAType int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
mama func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInFastLimit float64,
|
||||||
|
optInSlowLimit float64,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outMAMA []float64,
|
||||||
|
outFAMA []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
mavp func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
inPeriods []float64,
|
||||||
|
optInMinPeriod int32,
|
||||||
|
optInMaxPeriod int32,
|
||||||
|
optInMAType int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
midpoint func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
midprice func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inHigh []float64,
|
||||||
|
inLow []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
sar func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inHigh []float64,
|
||||||
|
inLow []float64,
|
||||||
|
optInAcceleration float64,
|
||||||
|
optInMaximum float64,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
sarext func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inHigh []float64,
|
||||||
|
inLow []float64,
|
||||||
|
optInStartValue float64,
|
||||||
|
optInOffsetOnReverse float64,
|
||||||
|
optInAccelerationInitLong float64,
|
||||||
|
optInAccelerationLong float64,
|
||||||
|
optInAccelerationMaxLong float64,
|
||||||
|
optInAccelerationInitShort float64,
|
||||||
|
optInAccelerationShort float64,
|
||||||
|
optInAccelerationMaxShort float64,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
sma func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
t3 func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
optInVFactor float64,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
tema func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
trima func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
|
|
||||||
|
wma func(
|
||||||
|
startIdx int32,
|
||||||
|
endIdx int32,
|
||||||
|
inReal []float64,
|
||||||
|
optInTimePeriod int32,
|
||||||
|
outBegIdx *int32,
|
||||||
|
outNBElement *int32,
|
||||||
|
outReal []float64,
|
||||||
|
) int32
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -101,6 +101,18 @@ func Load() (uintptr, error) {
|
|||||||
purego.RegisterLibFunc(&ema, ptr, "TA_EMA")
|
purego.RegisterLibFunc(&ema, ptr, "TA_EMA")
|
||||||
purego.RegisterLibFunc(&ht_trendline, ptr, "TA_HT_TRENDLINE")
|
purego.RegisterLibFunc(&ht_trendline, ptr, "TA_HT_TRENDLINE")
|
||||||
purego.RegisterLibFunc(&kama, ptr, "TA_KAMA")
|
purego.RegisterLibFunc(&kama, ptr, "TA_KAMA")
|
||||||
|
purego.RegisterLibFunc(&ma, ptr, "TA_MA")
|
||||||
|
purego.RegisterLibFunc(&mama, ptr, "TA_MAMA")
|
||||||
|
purego.RegisterLibFunc(&mavp, ptr, "TA_MAVP")
|
||||||
|
purego.RegisterLibFunc(&midpoint, ptr, "TA_MIDPOINT")
|
||||||
|
purego.RegisterLibFunc(&midprice, ptr, "TA_MIDPRICE")
|
||||||
|
purego.RegisterLibFunc(&sar, ptr, "TA_SAR")
|
||||||
|
purego.RegisterLibFunc(&sarext, ptr, "TA_SAREXT")
|
||||||
|
purego.RegisterLibFunc(&sma, ptr, "TA_SMA")
|
||||||
|
purego.RegisterLibFunc(&t3, ptr, "TA_T3")
|
||||||
|
purego.RegisterLibFunc(&tema, ptr, "TA_TEMA")
|
||||||
|
purego.RegisterLibFunc(&trima, ptr, "TA_TRIMA")
|
||||||
|
purego.RegisterLibFunc(&wma, ptr, "TA_WMA")
|
||||||
|
|
||||||
return ptr, nil
|
return ptr, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,3 +204,438 @@ func KAMA(inReal []float64, inTimePeriod int) []float64 {
|
|||||||
|
|
||||||
return outReal
|
return outReal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MA - Generic moving-average dispatcher that forwards the job to a concrete MA implementation selected by optInMAType.
|
||||||
|
// Single uniform interface over all TA-Lib moving averages.
|
||||||
|
//
|
||||||
|
// outReal = MA_of_type(optInMAType)(inReal, optInTimePeriod); default type = SMA
|
||||||
|
//
|
||||||
|
// Note: A period of 1 performs no smoothing for every MAType: the output is a copy of the input.
|
||||||
|
// `TA_MAType_DISABLED` bypasses smoothing explicitly, for any period: the output is a copy of the input with a lookback of 0.
|
||||||
|
// Every function that takes an MAType parameter accepts it.
|
||||||
|
func MA(inReal []float64, inTimePeriod int, inMAType MAType) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := ma(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
int32(inMAType),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("MA", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAMA - MESA Adaptive Moving Average: an adaptive EMA whose smoothing factor is driven by the dominant-cycle phase rate measured with a Hilbert transform.
|
||||||
|
// Emits two lines, MAMA and its slower follower FAMA.
|
||||||
|
// MAMA crossing above FAMA is bullish; crossing below is bearish.
|
||||||
|
//
|
||||||
|
// phase = atan(Q1/I1) in degrees; deltaPhase = max(1, prevPhase - phase)
|
||||||
|
// alpha = max(fastLimit/deltaPhase, slowLimit) if deltaPhase>1 else fastLimit
|
||||||
|
// MAMA = alpha*price + (1-alpha)*MAMA_prev
|
||||||
|
// FAMA = (alpha/2)*MAMA + (1-alpha/2)*FAMA_prev
|
||||||
|
// @param inReal Input data series
|
||||||
|
// @param inFastLimit Upper bound on the adaptive smoothing factor; default 0.5 (0.01 to 0.99)
|
||||||
|
// @param inSlowLimit Lower bound on the adaptive smoothing factor; default 0.05 (0.01 to 0.99)
|
||||||
|
func MAMA(inReal []float64, inFastLimit, inSlowLimit float64) ([]float64, []float64) {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outMAMA = make([]float64, len(inReal))
|
||||||
|
outFAMA = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := mama(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
inFastLimit,
|
||||||
|
inSlowLimit,
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outMAMA,
|
||||||
|
outFAMA,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("MAMA", "result", retCode)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outMAMA, outFAMA
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAVP - Moving average whose period varies per bar, driven by a companion period series.
|
||||||
|
// For each bar it computes an MA of the selected type over the (clamped) period given by inPeriods.
|
||||||
|
//
|
||||||
|
// p_i = clamp((int)inPeriods[startIdx+i], optInMinPeriod, optInMaxPeriod); outReal[i] = MA(inReal, p_i, optInMAType) at bar startIdx+i
|
||||||
|
//
|
||||||
|
// Note: Fractional per-bar periods are truncated to whole numbers before being clamped to the minimum and maximum period.
|
||||||
|
// Period values of 1 perform no smoothing (the bar's output equals its input); the minimum allowed period is 1 since 0.6.5.
|
||||||
|
// @param inReal Input data series
|
||||||
|
// @param inPeriods per-bar desired MA period
|
||||||
|
// @param inMinPeriod Lower clamp for the per-bar period; default 2 (1-100000)
|
||||||
|
// @param inMaxPeriod Upper clamp for the per-bar period; default 30 (1-100000)
|
||||||
|
// @param inMAType Type of moving average to compute; default talib.MA_SMA
|
||||||
|
func MAVP(inReal, inPeriods []float64, inMinPeriod, inMaxPeriod int, inMAType MAType) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := mavp(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
inPeriods,
|
||||||
|
int32(inMinPeriod),
|
||||||
|
int32(inMaxPeriod),
|
||||||
|
int32(inMAType),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("MAVP", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// MidPoint - Midpoint over a period: the average of the highest and lowest input values within the lookback window.
|
||||||
|
// A single-series overlap smoother (use MIDPRICE for separate high/low price bars).
|
||||||
|
//
|
||||||
|
// MIDPOINT = (Highest(inReal, period) + Lowest(inReal, period)) / 2
|
||||||
|
// @param inReal Input data series
|
||||||
|
// @param inTimePeriod Lookback window length; default 14 (2-100000)
|
||||||
|
func MidPoint(inReal []float64, inTimePeriod int) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := midpoint(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("MidPoint", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// MidPrice - Midpoint of the price range over a rolling window: the average of the highest high and lowest low across the last optInTimePeriod bars.
|
||||||
|
// An overlap-study line plotted on price.
|
||||||
|
//
|
||||||
|
// MIDPRICE = (Highest(High, N) + Lowest(Low, N)) / 2, over the N=optInTimePeriod bars ending at each index
|
||||||
|
// @param inHigh Input high price series
|
||||||
|
// @param inLow Input low price series
|
||||||
|
// @param inTimePeriod Lookback window length; default 14 (2-100000)
|
||||||
|
func MidPrice(inHigh, inLow []float64, inTimePeriod int) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inHigh) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inHigh))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := midprice(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inHigh,
|
||||||
|
inLow,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("MidPrice", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAR - Wilder's Parabolic SAR (Stop And Reverse): a trailing stop/reverse level that accelerates toward price via an acceleration factor.
|
||||||
|
// Signals trend direction and trailing exit points.
|
||||||
|
// SAR below price = uptrend (long);
|
||||||
|
// SAR above price = downtrend (short).
|
||||||
|
// Price crossing SAR flips direction.
|
||||||
|
//
|
||||||
|
// SAR_next = SAR + af * (EP - SAR)
|
||||||
|
// EP = extreme point (highest high in long / lowest low in short); af starts at Acceleration, += Acceleration each new EP, capped at Maximum.
|
||||||
|
// On penetration: reverse, SAR := prior EP, reset af = Acceleration. SAR clamped each bar so it does not penetrate the prior/current bar's range.
|
||||||
|
// @param inHigh Input high price series
|
||||||
|
// @param inLow Input low price series
|
||||||
|
// @param inAcceleration Step added to the acceleration factor on each new extreme point; default 0.02 (>=0)
|
||||||
|
// @param inMaximum Ceiling on the acceleration factor; default 0.2 (>=0)
|
||||||
|
func SAR(inHigh, inLow []float64, inAcceleration, inMaximum float64) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inHigh) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inHigh))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := sar(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inHigh,
|
||||||
|
inLow,
|
||||||
|
inAcceleration,
|
||||||
|
inMaximum,
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("SAR", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// SARExt - Extended Parabolic SAR (stop and reverse) giving the caller full control over the initial state and separate acceleration factors for long and short positions.
|
||||||
|
// Unlike SAR, it returns negative values while short so reversals are distinguishable.
|
||||||
|
// Sign flip of the output marks a trend reversal (positive=long stop, negative=short stop).
|
||||||
|
//
|
||||||
|
// SAR_next = SAR + AF*(EP - SAR), then clamped within the prior and current bar's range.
|
||||||
|
// On penetration, reverse: set SAR=EP (clamped), reset AF to its Init value, EP=extreme of the new direction.
|
||||||
|
// Output is +SAR when long, -SAR when short. On reversal an optional offset is applied: long->short SAR*(1+offset), short->long SAR*(1-offset).
|
||||||
|
// @param inHigh Input high price series
|
||||||
|
// @param inLow Input low price series
|
||||||
|
// @param inStartValue Initial SAR/direction: 0 auto, >0 start long at value, <0 start short at |value|; default 0 (any real number)
|
||||||
|
// @param inOffsetOnReverse Fractional offset applied to the stop on each reversal; default 0 (>=0)
|
||||||
|
// @param inAccelerationInitLong Initial acceleration factor when long; default 0.02 (>=0)
|
||||||
|
// @param inAccelerationLong AF increment per new long extreme; default 0.02 (>=0)
|
||||||
|
// @param inAccelerationMaxLong Cap on the long acceleration factor; default 0.2 (>=0)
|
||||||
|
// @param inAccelerationInitShort Initial acceleration factor when short; default 0.02 (>=0)
|
||||||
|
// @param inAccelerationShort AF increment per new short extreme; default 0.02 (>=0)
|
||||||
|
// @param inAccelerationMaxShort Cap on the short acceleration factor; default 0.2 (>=0)
|
||||||
|
func SARExt(
|
||||||
|
inHigh, inLow []float64,
|
||||||
|
inStartValue, inOffsetOnReverse,
|
||||||
|
inAccelerationInitLong, inAccelerationLong, inAccelerationMaxLong,
|
||||||
|
inAccelerationInitShort, inAccelerationShort, inAccelerationMaxShort float64,
|
||||||
|
) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inHigh) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inHigh))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := sarext(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inHigh,
|
||||||
|
inLow,
|
||||||
|
inStartValue,
|
||||||
|
inOffsetOnReverse,
|
||||||
|
inAccelerationInitLong,
|
||||||
|
inAccelerationLong,
|
||||||
|
inAccelerationMaxLong,
|
||||||
|
inAccelerationInitShort,
|
||||||
|
inAccelerationShort,
|
||||||
|
inAccelerationMaxShort,
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("SARExt", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// SMA - Simple Moving Average: the unweighted arithmetic mean of the last N input values. Used to smooth a series.
|
||||||
|
//
|
||||||
|
// SMA_t = (1/N) * sum_{i=t-N+1}^{t} inReal_i
|
||||||
|
//
|
||||||
|
// Note: A period of 1 performs no smoothing: the output is a copy of the input. Allowed since 0.6.5 (issues #48/#59).
|
||||||
|
func SMA(inReal []float64, inTimePeriod int) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := sma(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("SMA", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// T3 - Tillson's T3: a low-lag moving average built from six chained EMAs, combined via volume-factor-weighted coefficients.
|
||||||
|
// Not the same as EMA3, despite both being called "triple EMA".
|
||||||
|
//
|
||||||
|
// k = 2/(period+1); e1=EMA(x), e2=EMA(e1), ... e6=EMA(e5) (six chained EMAs).
|
||||||
|
// v = vFactor: c1 = -v^3; c2 = 3(v^2 - c1); c3 = -6v^2 - 3(v - c1); c4 = 1 + 3v - c1 + 3v^2.
|
||||||
|
// T3 = c1e6 + c2e5 + c3e4 + c4e3
|
||||||
|
//
|
||||||
|
// Note: A period of 1 performs no smoothing: the output is a copy of the input. Allowed since 0.6.5 (issues #48/#59).
|
||||||
|
// @param inReal Input data series
|
||||||
|
// @param inTimePeriod EMA period for each of the six stages; default 5 (2-100000)
|
||||||
|
// @param inVFactor Volume factor weighting the coefficients (0 = plain triple EMA, higher = more DEMA-like sharpening); default 0.7 (0-1)
|
||||||
|
func T3(inReal []float64, inTimePeriod int, inVFactor float64) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := t3(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
inVFactor,
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("T3", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEMA - Triple Exponential Moving Average: a smoothed price overlay built from three successively-applied EMAs to reduce lag versus a plain EMA.
|
||||||
|
// Distinct from EMA3, also called "triple EMA" in the literature.
|
||||||
|
//
|
||||||
|
// EMA1=EMA(t,period); EMA2=EMA(EMA1,period); EMA3=EMA(EMA2,period); TEMA = 3EMA1 - 3EMA2 + EMA3
|
||||||
|
//
|
||||||
|
// Note: A period of 1 performs no smoothing: the output is a copy of the input. Allowed since 0.6.5 (issues #48/#59).
|
||||||
|
func TEMA(inReal []float64, inTimePeriod int) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := tema(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("TEMA", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// TRIMA - Triangular Moving Average: a double-smoothed moving average that weights prices toward the middle of the window most heavily.
|
||||||
|
// Equivalent to an SMA of an SMA, computed here via an incremental triangular-weighted running numerator.
|
||||||
|
//
|
||||||
|
// Weights rise then fall (4-period: (1a+2b+2c+1d)/6; 5-period: (1a+2b+3c+2d+1e)/9).
|
||||||
|
// With n = period>>1: odd divides by (n+1)^2, even by n(n+1).
|
||||||
|
// Equivalent to odd: SMA(SMA(x,(period+1)/2),(period+1)/2); even: SMA(SMA(x,period/2),period/2+1).
|
||||||
|
//
|
||||||
|
// Note: Follows the generally accepted (Metastock) definition rather than the TradeStation variant.
|
||||||
|
// A period of 1 performs no smoothing: the output is a copy of the input. Allowed since 0.6.5 (issues #48/#59).
|
||||||
|
func TRIMA(inReal []float64, inTimePeriod int) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := trima(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("TRIMA", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|
||||||
|
// WMA - Linearly weighted moving average: each of the last N prices is weighted by its position,
|
||||||
|
// oldest getting weight 1 and newest weight N. Smooths price while emphasizing recent bars.
|
||||||
|
//
|
||||||
|
// WMA = ( sum_{k=1..N} k * P_k ) / (N(N+1)/2), where P_N is the most recent bar
|
||||||
|
//
|
||||||
|
// Note: A period of 1 performs no smoothing: the output is a copy of the input. Allowed since 0.6.5 (issues #48/#59).
|
||||||
|
func WMA(inReal []float64, inTimePeriod int) []float64 {
|
||||||
|
var (
|
||||||
|
startIdx int32
|
||||||
|
endIdx = int32(len(inReal) - 1)
|
||||||
|
outBegIdx int32
|
||||||
|
outNBElement int32
|
||||||
|
outReal = make([]float64, len(inReal))
|
||||||
|
)
|
||||||
|
|
||||||
|
if retCode := wma(
|
||||||
|
startIdx,
|
||||||
|
endIdx,
|
||||||
|
inReal,
|
||||||
|
int32(inTimePeriod),
|
||||||
|
&outBegIdx,
|
||||||
|
&outNBElement,
|
||||||
|
outReal,
|
||||||
|
); retCode != 0 {
|
||||||
|
slog.Debug("WMA", "result", retCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outReal
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user