From 7cf9ab6e2478ab7c19662c8371488574b1a56e4f Mon Sep 17 00:00:00 2001 From: Alek Kim Date: Mon, 27 Jul 2026 16:52:33 +0900 Subject: [PATCH] feat(price-transform): add price transform and statistic function wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New file price_transform.go implements five new public wrappers: - AvgPrice (TA_AVGPRICE) – mean of OHLC per bar - MedPrice (TA_MEDPRICE) – (High + Low) / 2 - TypPrice (TA_TYPPRICE) – (High + Low + Close) / 3 - WCLPrice (TA_WCLPRICE) – (High + Low + 2×Close) / 4 - AvgDev (TA_AVGDEV) – rolling average absolute deviation from SMA - add corresponding low-level function pointer signatures in functions.go - register all five symbols in Load() in loader.go - update README.md with Price Transforms and Statistic Functions sections --- README.md | 6 ++ functions.go | 54 +++++++++++++++++ loader.go | 6 ++ price_transform.go | 145 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 price_transform.go diff --git a/README.md b/README.md index d9668fb..c823558 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,12 @@ This project currently exposes a focused subset of TA-Lib functions: **Overlap Studies** - `AccBands`, `BBands`, `DEMA`, `EMA`, `HT_TRENDLINE`, `KAMA`, `MA`, `MAMA`, `MAVP`, `MidPoint`, `MidPrice`, `SAR`, `SARExt`, `SMA`, `T3`, `TEMA`, `TRIMA`, `WMA` +**Price Transforms** +- `AvgPrice`, `MedPrice`, `TypPrice`, `WCLPrice` + +**Statistic Functions** +- `AvgDev` + ## Requirements - Go `1.26` diff --git a/functions.go b/functions.go index 1fd3700..6218cf2 100644 --- a/functions.go +++ b/functions.go @@ -876,4 +876,58 @@ var ( outNBElement *int32, outReal []float64, ) int32 + + avgdev func( + startIdx int32, + endIdx int32, + inReal []float64, + optInTimePeriod int32, + outBegIdx *int32, + outNBElement *int32, + outReal []float64, + ) int32 + + avgprice func( + startIdx int32, + endIdx int32, + inOpen []float64, + inHigh []float64, + inLow []float64, + inClose []float64, + outBegIdx *int32, + outNBElement *int32, + outReal []float64, + ) int32 + + medprice func( + startIdx int32, + endIdx int32, + inHigh []float64, + inLow []float64, + outBegIdx *int32, + outNBElement *int32, + outReal []float64, + ) int32 + + typprice func( + startIdx int32, + endIdx int32, + inHigh []float64, + inLow []float64, + inClose []float64, + outBegIdx *int32, + outNBElement *int32, + outReal []float64, + ) int32 + + wclprice func( + startIdx int32, + endIdx int32, + inHigh []float64, + inLow []float64, + inClose []float64, + outBegIdx *int32, + outNBElement *int32, + outReal []float64, + ) int32 ) diff --git a/loader.go b/loader.go index 0e16223..9f76fb1 100644 --- a/loader.go +++ b/loader.go @@ -114,6 +114,12 @@ func Load() (uintptr, error) { purego.RegisterLibFunc(&trima, ptr, "TA_TRIMA") purego.RegisterLibFunc(&wma, ptr, "TA_WMA") + purego.RegisterLibFunc(&avgdev, ptr, "TA_AVGDEV") + purego.RegisterLibFunc(&avgprice, ptr, "TA_AVGPRICE") + purego.RegisterLibFunc(&medprice, ptr, "TA_MEDPRICE") + purego.RegisterLibFunc(&typprice, ptr, "TA_TYPPRICE") + purego.RegisterLibFunc(&wclprice, ptr, "TA_WCLPRICE") + return ptr, nil } diff --git a/price_transform.go b/price_transform.go new file mode 100644 index 0000000..ac61314 --- /dev/null +++ b/price_transform.go @@ -0,0 +1,145 @@ +package talib + +import "log/slog" + +// AvgDev - Rolling average absolute deviation of a series from its own simple moving average over the last N periods. +// Measures dispersion around the window mean. Higher values indicate greater spread; zero when all values in the window are equal. +func AvgDev(inReal []float64, inTimePeriod int) []float64 { + var ( + startIdx int32 + endIdx = int32(len(inReal) - 1) + outBegIdx int32 + outNBElement int32 + outReal = make([]float64, len(inReal)) + ) + + if retCode := avgdev( + startIdx, + endIdx, + inReal, + int32(inTimePeriod), + &outBegIdx, + &outNBElement, + outReal, + ); retCode != 0 { + slog.Debug("AVGDEV", "result", retCode) + return nil + } + + return outReal +} + +// AvgPrice - Average Price: the arithmetic mean of each bar's open, high, low, and close. +// A price-transform overlap condensing OHLC into a single representative price. +func AvgPrice(inOpen, inHigh, inLow, inClose []float64) []float64 { + var ( + startIdx int32 + endIdx = int32(len(inOpen) - 1) + outBegIdx int32 + outNBElement int32 + outReal = make([]float64, len(inOpen)) + ) + + if retCode := avgprice( + startIdx, + endIdx, + inOpen, + inHigh, + inLow, + inClose, + &outBegIdx, + &outNBElement, + outReal, + ); retCode != 0 { + slog.Debug("AVGPRICE", "result", retCode) + return nil + } + + return outReal +} + +// MedPrice - Median Price: the midpoint of each bar's high and low. A price-transform overlay. +// +// Median Price = (High + Low) / 2 +func MedPrice(inHigh, inLow []float64) []float64 { + var ( + startIdx int32 + endIdx = int32(len(inHigh) - 1) + outBegIdx int32 + outNBElement int32 + outReal = make([]float64, len(inHigh)) + ) + + if retCode := medprice( + startIdx, + endIdx, + inHigh, + inLow, + &outBegIdx, + &outNBElement, + outReal, + ); retCode != 0 { + slog.Debug("MEDPRICE", "result", retCode) + return nil + } + + return outReal +} + +// TypPrice - Typical Price: the average of the high, low, and close of each bar. A single representative price per period. +// +// Typical Price = (High + Low + Close) / 3 +func TypPrice(inHigh, inLow, inClose []float64) []float64 { + var ( + startIdx int32 + endIdx = int32(len(inHigh) - 1) + outBegIdx int32 + outNBElement int32 + outReal = make([]float64, len(inHigh)) + ) + + if retCode := typprice( + startIdx, + endIdx, + inHigh, + inLow, + inClose, + &outBegIdx, + &outNBElement, + outReal, + ); retCode != 0 { + slog.Debug("TYPPRICE", "result", retCode) + return nil + } + + return outReal +} + +// WCLPrice - Weighted Close Price: a per-bar price average giving the close double weight relative to high and low. +// +// Weighted Close Price = (High + Low + 2 * Close) / 4 +func WCLPrice(inHigh, inLow, inClose []float64) []float64 { + var ( + startIdx int32 + endIdx = int32(len(inHigh) - 1) + outBegIdx int32 + outNBElement int32 + outReal = make([]float64, len(inHigh)) + ) + + if retCode := wclprice( + startIdx, + endIdx, + inHigh, + inLow, + inClose, + &outBegIdx, + &outNBElement, + outReal, + ); retCode != 0 { + slog.Debug("WCLPRICE", "result", retCode) + return nil + } + + return outReal +}