Files
talib/statistic_functions.go
beejay fc504d0c01 feat(stats): add regression and volatility wrappers
- add native TA-Lib bindings in functions.go for beta, correl, linear regression, stddev, tsf, and variance
- register the new TA-Lib symbols in loader.go
- add public wrappers in statistic_functions.go for Beta, Correl, LinearReg, LinearRegAngle, LinearRegIntercept, LinearRegSlope, StdDev, TSF, and Var
- update README.md to document Price Transforms and Statistic Functions
2026-07-27 18:10:46 +09:00

289 lines
8.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package talib
// Beta - Beta: the slope of a least-squares linear regression of one series' percentage returns (y, from inReal1) against another's (x, from inReal0) over a rolling window.
// Measures how much a security moves relative to a market index.
// Beta = 1 moves with the index; < 1 less volatile, > 1 more volatile.
//
// @param inReal0: Series whose returns are the regression x (market/index)
// @param inReal1: Series whose returns are the regression y (security)
// @param optInTimePeriod: Rolling window length (number of returns) for the regression sums; default is 5 (1-100000)
//
// @return: regression slope of inReal1-returns on inReal0-returns
func Beta(inReal0, inReal1 []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal0) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal0))
)
if retCode := beta(
startIdx,
endIdx,
inReal0,
inReal1,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// Correl - Pearson's correlation coefficient (r) between two input series over a rolling window of optInTimePeriod bars.
// Measures how linearly the two series move together. r near +1: strong positive co-movement; near -1: strong inverse; near 0: no linear relationship.
//
// r = (sumXY - sumX*sumY/n) / sqrt((sumX2 - sumX^2/n) * (sumY2 - sumY^2/n)), n = optInTimePeriod, sums over the window
//
// Note: When the correlation is undefined for a window (for example a constant series), the output is 0 rather than an error or NaN.
//
// @param inReal0: First data series (X)
// @param inReal1: Second data series (Y)
// @param optInTimePeriod: Rolling window length (number of bars) for the correlation sums; default is 30 (2-100000)
//
// @return: Correlation coefficient r in [-1, 1]
func Correl(inReal0, inReal1 []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal0) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal0))
)
if retCode := correl(
startIdx,
endIdx,
inReal0,
inReal1,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// LinearReg - Least-squares straight-line fit over the last optInTimePeriod bars, reported as the fitted line value at the window endpoint (b + m*(period-1)).
//
// @param inReal: Input series
// @param optInTimePeriod: Number of bars (period) for the regression; default is 14 (2-100000)
//
// @return: Fitted line value at the window endpoint
func LinearReg(inReal []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := linearreg(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// LinearRegAngle - The angle, in degrees, of the least-squares best-fit line over the last N points.
// It is the LINEARREG_SLOPE value passed through atan and converted to degrees.
// Positive angle = rising fit line, negative = falling; magnitude reflects steepness.
//
// m = (N·SumXY SumX·SumY) / (SumX² N·SumXSqr), with SumX=N(N1)/2, SumXSqr=N(N1)(2N1)/6; angle = atan(m)·(180/π)
func LinearRegAngle(inReal []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := linearreg_angle(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// LinearRegIntercept - Returns the y-intercept (b) of the least-squares regression line fitted over the last optInTimePeriod values.
// Part of the linear-regression family (LINEARREG, SLOPE, ANGLE, TSF).
//
// Fit y = b + m·x over the window with x = bars-ago (x=0 is the current bar, x=period-1 the oldest).
// With SumX = period(period-1)/2, SumXSqr = period(period-1)(2·period-1)/6, Divisor = SumX² period·SumXSqr:
// m = (period·SumXY SumX·SumY) / Divisor
// b = (SumY m·SumX) / period ← output
func LinearRegIntercept(inReal []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := linearreg_intercept(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// LinearRegSlope - Slope 'm' of the least-squares best-fit line (y = b + m*x) over the last optInTimePeriod bars.
// Reports the per-bar rate of change of the fitted trend line.
// Positive slope = rising trend, negative = falling; magnitude is price change per bar.
//
// m = (n·SumXY SumX·SumY) / Divisor
// SumX = n(n1)/2, SumXSqr = n(n1)(2n1)/6, Divisor = SumX² n·SumXSqr
// SumXY = Σ i·y[todayi], SumY = Σ y[todayi], i=0..n1, n=period, y=inReal
func LinearRegSlope(inReal []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := linearreg_slope(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// StdDev - Rolling standard deviation of a series over a window, scaled by a deviations multiplier.
// Delegates to VAR, then takes the square root.
//
// Note: Uses population variance (divides by the period, not period minus one), so results differ slightly from the sample standard deviation used by some tools.
// @param inReal: Input series
// @param optInTimePeriod: Number of bars (period) for the rolling window; default is 5 (2-100000)
// @param optInNbDev: Multiplier for the standard deviation; default is 1.0 (0.0-500.0)
//
// @return: Rolling standard deviation scaled by optInNbDev
func StdDev(inReal []float64, optInTimePeriod int, optInNbDev float64) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := stddev(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
optInNbDev,
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// TSF - Time Series Forecast: fits a least-squares linear regression line over the last N bars and projects it one x-step beyond talib.LinearReg.
// Same regression as talib.LinearReg but evaluated at x=period instead of x=period-1.
//
// Fit y=b+mx over window (x=0..N-1): m = (NSumXY - SumXSumY)/(SumX^2 - NSumXSqr), b = (SumY - mSumX)/N; output = b + mN.
// With SumX=N(N-1)/2, SumXSqr=N(N-1)(2N-1)/6.
func TSF(inReal []float64, optInTimePeriod int) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := tsf(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}
// Var - Rolling population variance of a real series over a given period.
// Measures dispersion of values around their mean. Higher values indicate greater dispersion; 0 means constant input.
//
// Var = (SumX2 - SumX^2/n) / n, n = optInTimePeriod, sums over the window
//
// Note: Computes population variance (divides by the period), not the sample variance (n-1) used by some definitions.
// The deviation-count parameter is accepted but has no effect on the result.
func Var(inReal []float64, optInTimePeriod int, optInNbDev float64) []float64 {
var (
startIdx int32
endIdx = int32(len(inReal) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]float64, len(inReal))
)
if retCode := variance(
startIdx,
endIdx,
inReal,
int32(optInTimePeriod),
optInNbDev,
&outBegIdx,
&outNBElement,
outReal,
); retCode != 0 {
return nil
}
return outReal
}