feat: 15 funciones finance — indicadores, riesgo e IO de mercado
11 funciones puras con implementación real: SMA, EMA, RSI, BollingerBands, VWAP, LogReturn, AnnualizedVolatility, SharpeRatio, MaxDrawdown, NormalizeOHLCV, TickToOHLCV 4 funciones impuras (stubs): FetchOHLCV, StreamTicks, WriteOHLCVToParquet, LoadOHLCVFromDuckDB Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package finance
|
||||
|
||||
import "math"
|
||||
|
||||
// AnnualizedVolatility calcula la volatilidad anualizada a partir de una serie de retornos.
|
||||
// periodsPerYear indica cuantos periodos hay en un anio (e.g. 252 para retornos diarios).
|
||||
// Retorna stddev(returns) * sqrt(periodsPerYear).
|
||||
func AnnualizedVolatility(returns []float64, periodsPerYear float64) float64 {
|
||||
n := len(returns)
|
||||
if n < 2 {
|
||||
return 0
|
||||
}
|
||||
var sum float64
|
||||
for _, r := range returns {
|
||||
sum += r
|
||||
}
|
||||
mean := sum / float64(n)
|
||||
var variance float64
|
||||
for _, r := range returns {
|
||||
diff := r - mean
|
||||
variance += diff * diff
|
||||
}
|
||||
variance /= float64(n - 1)
|
||||
return math.Sqrt(variance) * math.Sqrt(periodsPerYear)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: annualized_volatility
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func AnnualizedVolatility(returns []float64, periodsPerYear float64) float64"
|
||||
description: "Calcula la volatilidad anualizada a partir de una serie de retornos y la frecuencia de los periodos."
|
||||
tags: [finance, volatility, risk, annualized]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [math]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/annualized_volatility.go"
|
||||
---
|
||||
|
||||
# annualized_volatility
|
||||
|
||||
Calcula la volatilidad anualizada como `stddev(returns) * sqrt(periodsPerYear)`. Usa desviacion estandar muestral (n-1).
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
vol := finance.AnnualizedVolatility([]float64{0.01, -0.02, 0.015, 0.005, -0.01}, 252)
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
package finance
|
||||
|
||||
import "math"
|
||||
|
||||
// BollingerBands calcula las bandas de Bollinger: upper, middle (SMA), lower.
|
||||
// Los primeros period-1 elementos de cada slice son 0.
|
||||
func BollingerBands(data []float64, period int, numStdDev float64) (upper, middle, lower []float64) {
|
||||
n := len(data)
|
||||
upper = make([]float64, n)
|
||||
middle = make([]float64, n)
|
||||
lower = make([]float64, n)
|
||||
if period <= 0 || period > n {
|
||||
return
|
||||
}
|
||||
for i := period - 1; i < n; i++ {
|
||||
var sum float64
|
||||
for j := i - period + 1; j <= i; j++ {
|
||||
sum += data[j]
|
||||
}
|
||||
mean := sum / float64(period)
|
||||
var variance float64
|
||||
for j := i - period + 1; j <= i; j++ {
|
||||
diff := data[j] - mean
|
||||
variance += diff * diff
|
||||
}
|
||||
std := math.Sqrt(variance / float64(period))
|
||||
middle[i] = mean
|
||||
upper[i] = mean + numStdDev*std
|
||||
lower[i] = mean - numStdDev*std
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: bollinger_bands
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func BollingerBands(data []float64, period int, numStdDev float64) (upper, middle, lower []float64)"
|
||||
description: "Calcula las bandas de Bollinger (upper, middle, lower) para una serie de precios."
|
||||
tags: [finance, indicator, bollinger, bands]
|
||||
uses_functions: []
|
||||
uses_types: [bollinger_result_go_finance]
|
||||
returns: [bollinger_result_go_finance]
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [math]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/bollinger_bands.go"
|
||||
---
|
||||
|
||||
# bollinger_bands
|
||||
|
||||
Calcula las bandas de Bollinger. La banda media es la SMA, y las bandas superior e inferior estan a `numStdDev` desviaciones estandar de la media. Usa desviacion estandar poblacional.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
upper, middle, lower := finance.BollingerBands(
|
||||
[]float64{22, 24, 23, 25, 26, 28, 27, 29, 30, 28},
|
||||
5, 2.0,
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
package finance
|
||||
|
||||
// EMA calcula la media movil exponencial de data con el periodo dado.
|
||||
// El primer valor valido se inicializa con la SMA de los primeros period elementos.
|
||||
// Los primeros period-1 elementos del resultado son 0.
|
||||
func EMA(data []float64, period int) []float64 {
|
||||
n := len(data)
|
||||
result := make([]float64, n)
|
||||
if period <= 0 || period > n {
|
||||
return result
|
||||
}
|
||||
k := 2.0 / float64(period+1)
|
||||
// Seed con SMA
|
||||
var sum float64
|
||||
for i := 0; i < period; i++ {
|
||||
sum += data[i]
|
||||
}
|
||||
result[period-1] = sum / float64(period)
|
||||
for i := period; i < n; i++ {
|
||||
result[i] = data[i]*k + result[i-1]*(1-k)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: ema
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func EMA(data []float64, period int) []float64"
|
||||
description: "Calcula la media movil exponencial (EMA) sobre una serie de datos con un periodo dado."
|
||||
tags: [finance, indicator, ema, moving-average]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/ema.go"
|
||||
---
|
||||
|
||||
# ema
|
||||
|
||||
Calcula la media movil exponencial (Exponential Moving Average). Se inicializa con la SMA de los primeros `period` elementos. El multiplicador es `2 / (period + 1)`.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
result := finance.EMA([]float64{10, 11, 12, 13, 14, 15}, 3)
|
||||
// result[2] = SMA de los primeros 3 = 11.0
|
||||
// result[3] en adelante usa suavizado exponencial
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
package finance
|
||||
|
||||
import "fmt"
|
||||
|
||||
// FetchOHLCV obtiene datos OHLCV de un exchange para un simbolo e intervalo dados.
|
||||
// TODO: implementar conexion real al exchange.
|
||||
func FetchOHLCV(symbol, interval string) ([][]float64, error) {
|
||||
return nil, fmt.Errorf("not implemented: FetchOHLCV(%s, %s)", symbol, interval)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: fetch_ohlcv
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func FetchOHLCV(symbol, interval string) ([][]float64, error)"
|
||||
description: "Obtiene datos OHLCV de un exchange para un simbolo e intervalo dados."
|
||||
tags: [finance, io, exchange, fetch]
|
||||
uses_functions: []
|
||||
uses_types: [ohlcv_go_finance]
|
||||
returns: [ohlcv_go_finance]
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [fmt]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/fetch_ohlcv.go"
|
||||
---
|
||||
|
||||
# fetch_ohlcv
|
||||
|
||||
Stub para obtener datos OHLCV de un exchange. Pendiente de implementacion.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
data, err := finance.FetchOHLCV("BTC/USDT", "1h")
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
package finance
|
||||
|
||||
import "fmt"
|
||||
|
||||
// LoadOHLCVFromDuckDB carga datos OHLCV ejecutando una query en una base DuckDB.
|
||||
// TODO: implementar conexion real a DuckDB.
|
||||
func LoadOHLCVFromDuckDB(dbPath, query string) ([][]float64, error) {
|
||||
return nil, fmt.Errorf("not implemented: LoadOHLCVFromDuckDB(%s, %s)", dbPath, query)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: load_ohlcv_from_duckdb
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func LoadOHLCVFromDuckDB(dbPath, query string) ([][]float64, error)"
|
||||
description: "Carga datos OHLCV ejecutando una query SQL en una base de datos DuckDB."
|
||||
tags: [finance, io, duckdb, load]
|
||||
uses_functions: []
|
||||
uses_types: [ohlcv_go_finance]
|
||||
returns: [ohlcv_go_finance]
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [fmt]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/load_ohlcv_from_duckdb.go"
|
||||
---
|
||||
|
||||
# load_ohlcv_from_duckdb
|
||||
|
||||
Stub para cargar datos OHLCV desde DuckDB. Pendiente de implementacion.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
data, err := finance.LoadOHLCVFromDuckDB("/data/market.duckdb", "SELECT * FROM ohlcv WHERE symbol='BTC'")
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
package finance
|
||||
|
||||
import "math"
|
||||
|
||||
// LogReturn calcula el retorno logaritmico entre dos precios.
|
||||
// Retorna ln(priceEnd / priceStart). Si priceStart <= 0 o priceEnd <= 0, retorna 0.
|
||||
func LogReturn(priceStart, priceEnd float64) float64 {
|
||||
if priceStart <= 0 || priceEnd <= 0 {
|
||||
return 0
|
||||
}
|
||||
return math.Log(priceEnd / priceStart)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: log_return
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func LogReturn(priceStart, priceEnd float64) float64"
|
||||
description: "Calcula el retorno logaritmico entre un precio inicial y un precio final."
|
||||
tags: [finance, return, logarithmic, atomic]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [math]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/log_return.go"
|
||||
---
|
||||
|
||||
# log_return
|
||||
|
||||
Calcula el retorno logaritmico: `ln(priceEnd / priceStart)`. Si alguno de los precios es <= 0, retorna 0.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
r := finance.LogReturn(100.0, 110.0)
|
||||
// r ~ 0.09531 (aprox 9.53%)
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
package finance
|
||||
|
||||
// MaxDrawdown calcula el maximo drawdown de una serie de valores (e.g. equity curve).
|
||||
// Retorna la magnitud del drawdown (valor positivo entre 0 y 1 como fraccion del pico),
|
||||
// y los indices de inicio (pico) y fin (valle) del peor drawdown.
|
||||
// Si la serie tiene menos de 2 elementos, retorna 0, 0, 0.
|
||||
func MaxDrawdown(values []float64) (maxDD float64, start, end int) {
|
||||
n := len(values)
|
||||
if n < 2 {
|
||||
return 0, 0, 0
|
||||
}
|
||||
peakIdx := 0
|
||||
peak := values[0]
|
||||
for i := 1; i < n; i++ {
|
||||
if values[i] > peak {
|
||||
peak = values[i]
|
||||
peakIdx = i
|
||||
}
|
||||
dd := (peak - values[i]) / peak
|
||||
if dd > maxDD {
|
||||
maxDD = dd
|
||||
start = peakIdx
|
||||
end = i
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: max_drawdown
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func MaxDrawdown(values []float64) (maxDD float64, start, end int)"
|
||||
description: "Calcula el maximo drawdown de una curva de equity, retornando la magnitud y los indices pico-valle."
|
||||
tags: [finance, drawdown, risk, metric]
|
||||
uses_functions: []
|
||||
uses_types: [drawdown_result_go_finance]
|
||||
returns: [drawdown_result_go_finance]
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/max_drawdown.go"
|
||||
---
|
||||
|
||||
# max_drawdown
|
||||
|
||||
Calcula el maximo drawdown (caida maxima desde un pico hasta un valle) como fraccion del pico. Retorna la magnitud (0 a 1) y los indices de inicio y fin.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
dd, s, e := finance.MaxDrawdown([]float64{100, 120, 90, 110, 80})
|
||||
// dd = (120-80)/120 = 0.3333, s = 1, e = 4
|
||||
```
|
||||
@@ -0,0 +1,17 @@
|
||||
package finance
|
||||
|
||||
// NormalizeOHLCV ajusta slices de precios OHLCV multiplicando por un factor.
|
||||
func NormalizeOHLCV(open, high, low, close []float64, factor float64) ([]float64, []float64, []float64, []float64) {
|
||||
n := len(open)
|
||||
nOpen := make([]float64, n)
|
||||
nHigh := make([]float64, n)
|
||||
nLow := make([]float64, n)
|
||||
nClose := make([]float64, n)
|
||||
for i := 0; i < n; i++ {
|
||||
nOpen[i] = open[i] * factor
|
||||
nHigh[i] = high[i] * factor
|
||||
nLow[i] = low[i] * factor
|
||||
nClose[i] = close[i] * factor
|
||||
}
|
||||
return nOpen, nHigh, nLow, nClose
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: normalize_ohlcv
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func NormalizeOHLCV(open, high, low, close []float64, factor float64) ([]float64, []float64, []float64, []float64)"
|
||||
description: "Ajusta slices de precios OHLCV multiplicando cada valor por un factor dado."
|
||||
tags: [finance, ohlcv, normalize, adjust]
|
||||
uses_functions: []
|
||||
uses_types: [ohlcv_go_finance]
|
||||
returns: [ohlcv_go_finance]
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/normalize_ohlcv.go"
|
||||
---
|
||||
|
||||
# normalize_ohlcv
|
||||
|
||||
Ajusta slices de precios OHLCV (open, high, low, close) multiplicando cada elemento por un factor escalar. Util para ajustes por splits, conversiones de divisa, o normalizacion de series.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
o, h, l, c := finance.NormalizeOHLCV(
|
||||
[]float64{100, 200},
|
||||
[]float64{110, 210},
|
||||
[]float64{90, 190},
|
||||
[]float64{105, 205},
|
||||
2.0,
|
||||
)
|
||||
// o = [200, 400], h = [220, 420], l = [180, 380], c = [210, 410]
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
package finance
|
||||
|
||||
// RSI calcula el Relative Strength Index.
|
||||
// Usa el metodo de suavizado de Wilder (EMA con alpha = 1/period).
|
||||
// Los primeros period elementos del resultado son 0.
|
||||
func RSI(data []float64, period int) []float64 {
|
||||
n := len(data)
|
||||
result := make([]float64, n)
|
||||
if period <= 0 || n < period+1 {
|
||||
return result
|
||||
}
|
||||
var gainSum, lossSum float64
|
||||
for i := 1; i <= period; i++ {
|
||||
change := data[i] - data[i-1]
|
||||
if change > 0 {
|
||||
gainSum += change
|
||||
} else {
|
||||
lossSum -= change
|
||||
}
|
||||
}
|
||||
avgGain := gainSum / float64(period)
|
||||
avgLoss := lossSum / float64(period)
|
||||
if avgLoss == 0 {
|
||||
result[period] = 100
|
||||
} else {
|
||||
rs := avgGain / avgLoss
|
||||
result[period] = 100 - 100/(1+rs)
|
||||
}
|
||||
for i := period + 1; i < n; i++ {
|
||||
change := data[i] - data[i-1]
|
||||
var gain, loss float64
|
||||
if change > 0 {
|
||||
gain = change
|
||||
} else {
|
||||
loss = -change
|
||||
}
|
||||
avgGain = (avgGain*float64(period-1) + gain) / float64(period)
|
||||
avgLoss = (avgLoss*float64(period-1) + loss) / float64(period)
|
||||
if avgLoss == 0 {
|
||||
result[i] = 100
|
||||
} else {
|
||||
rs := avgGain / avgLoss
|
||||
result[i] = 100 - 100/(1+rs)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: rsi
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func RSI(data []float64, period int) []float64"
|
||||
description: "Calcula el Relative Strength Index (RSI) usando suavizado de Wilder."
|
||||
tags: [finance, indicator, rsi, momentum]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/rsi.go"
|
||||
---
|
||||
|
||||
# rsi
|
||||
|
||||
Calcula el Relative Strength Index (RSI) con el metodo de suavizado de Wilder. Los primeros `period` elementos son 0. El RSI oscila entre 0 y 100.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
result := finance.RSI([]float64{44, 44.34, 44.09, 43.61, 44.33, 44.83, 45.10, 45.42, 45.84}, 5)
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
package finance
|
||||
|
||||
import "math"
|
||||
|
||||
// SharpeRatio calcula el ratio de Sharpe.
|
||||
// riskFreeRate es la tasa libre de riesgo por periodo.
|
||||
// periodsPerYear indica cuantos periodos hay en un anio (e.g. 252 para diario).
|
||||
// Formula: (mean(returns) - riskFreeRate) / stddev(returns) * sqrt(periodsPerYear)
|
||||
func SharpeRatio(returns []float64, riskFreeRate float64, periodsPerYear float64) float64 {
|
||||
n := len(returns)
|
||||
if n < 2 {
|
||||
return 0
|
||||
}
|
||||
var sum float64
|
||||
for _, r := range returns {
|
||||
sum += r
|
||||
}
|
||||
mean := sum / float64(n)
|
||||
var variance float64
|
||||
for _, r := range returns {
|
||||
diff := r - mean
|
||||
variance += diff * diff
|
||||
}
|
||||
std := math.Sqrt(variance / float64(n-1))
|
||||
if std == 0 {
|
||||
return 0
|
||||
}
|
||||
return (mean - riskFreeRate) / std * math.Sqrt(periodsPerYear)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: sharpe_ratio
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func SharpeRatio(returns []float64, riskFreeRate float64, periodsPerYear float64) float64"
|
||||
description: "Calcula el ratio de Sharpe anualizado a partir de retornos, tasa libre de riesgo y frecuencia."
|
||||
tags: [finance, sharpe, risk, ratio]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [math]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/sharpe_ratio.go"
|
||||
---
|
||||
|
||||
# sharpe_ratio
|
||||
|
||||
Calcula el ratio de Sharpe: `(mean(returns) - riskFreeRate) / stddev(returns) * sqrt(periodsPerYear)`. Usa desviacion estandar muestral.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
sr := finance.SharpeRatio([]float64{0.01, 0.02, -0.005, 0.015, 0.008}, 0.0001, 252)
|
||||
```
|
||||
@@ -0,0 +1,22 @@
|
||||
package finance
|
||||
|
||||
// SMA calcula la media movil simple de data con el periodo dado.
|
||||
// Retorna un slice de longitud len(data) donde los primeros period-1
|
||||
// elementos son 0 (sin datos suficientes).
|
||||
func SMA(data []float64, period int) []float64 {
|
||||
n := len(data)
|
||||
result := make([]float64, n)
|
||||
if period <= 0 || period > n {
|
||||
return result
|
||||
}
|
||||
var sum float64
|
||||
for i := 0; i < period; i++ {
|
||||
sum += data[i]
|
||||
}
|
||||
result[period-1] = sum / float64(period)
|
||||
for i := period; i < n; i++ {
|
||||
sum += data[i] - data[i-period]
|
||||
result[i] = sum / float64(period)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: sma
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func SMA(data []float64, period int) []float64"
|
||||
description: "Calcula la media movil simple (SMA) sobre una serie de datos con un periodo dado."
|
||||
tags: [finance, indicator, sma, moving-average]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/sma.go"
|
||||
---
|
||||
|
||||
# sma
|
||||
|
||||
Calcula la media movil simple (Simple Moving Average). Los primeros `period-1` elementos del resultado son 0 ya que no hay datos suficientes para calcular la media.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
result := finance.SMA([]float64{1, 2, 3, 4, 5}, 3)
|
||||
// result = [0, 0, 2, 3, 4]
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
package finance
|
||||
|
||||
import "fmt"
|
||||
|
||||
// StreamTicks abre un stream de ticks en tiempo real para un simbolo.
|
||||
// Retorna un canal de [2]float64 donde [0] es precio y [1] es volumen.
|
||||
// TODO: implementar conexion real via websocket.
|
||||
func StreamTicks(symbol string) (<-chan [2]float64, error) {
|
||||
return nil, fmt.Errorf("not implemented: StreamTicks(%s)", symbol)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: stream_ticks
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func StreamTicks(symbol string) (<-chan [2]float64, error)"
|
||||
description: "Abre un stream de ticks en tiempo real para un simbolo via websocket."
|
||||
tags: [finance, io, stream, realtime]
|
||||
uses_functions: []
|
||||
uses_types: [tick_go_finance]
|
||||
returns: [tick_go_finance]
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [fmt]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/stream_ticks.go"
|
||||
---
|
||||
|
||||
# stream_ticks
|
||||
|
||||
Stub para abrir un stream de ticks en tiempo real. Pendiente de implementacion.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
ch, err := finance.StreamTicks("ETH/USDT")
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
package finance
|
||||
|
||||
// TickToOHLCV agrega datos de ticks en velas OHLCV segun un intervalo en segundos.
|
||||
// prices, volumes y timestamps deben tener la misma longitud.
|
||||
// timestamps son unix seconds. intervalSecs define el ancho de cada vela.
|
||||
// Retorna slices de open, high, low, close, volume para cada vela generada.
|
||||
func TickToOHLCV(prices, volumes []float64, timestamps []int64, intervalSecs int64) (open, high, low, close, vol []float64) {
|
||||
n := len(prices)
|
||||
if n == 0 || intervalSecs <= 0 {
|
||||
return
|
||||
}
|
||||
bucketStart := timestamps[0] - (timestamps[0] % intervalSecs)
|
||||
o := prices[0]
|
||||
h := prices[0]
|
||||
l := prices[0]
|
||||
c := prices[0]
|
||||
v := volumes[0]
|
||||
|
||||
for i := 1; i < n; i++ {
|
||||
currentBucket := timestamps[i] - (timestamps[i] % intervalSecs)
|
||||
if currentBucket != bucketStart {
|
||||
// Cerrar la vela anterior
|
||||
open = append(open, o)
|
||||
high = append(high, h)
|
||||
low = append(low, l)
|
||||
close = append(close, c)
|
||||
vol = append(vol, v)
|
||||
// Nueva vela
|
||||
bucketStart = currentBucket
|
||||
o = prices[i]
|
||||
h = prices[i]
|
||||
l = prices[i]
|
||||
c = prices[i]
|
||||
v = volumes[i]
|
||||
} else {
|
||||
if prices[i] > h {
|
||||
h = prices[i]
|
||||
}
|
||||
if prices[i] < l {
|
||||
l = prices[i]
|
||||
}
|
||||
c = prices[i]
|
||||
v += volumes[i]
|
||||
}
|
||||
}
|
||||
// Cerrar ultima vela
|
||||
open = append(open, o)
|
||||
high = append(high, h)
|
||||
low = append(low, l)
|
||||
close = append(close, c)
|
||||
vol = append(vol, v)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
name: tick_to_ohlcv
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func TickToOHLCV(prices, volumes []float64, timestamps []int64, intervalSecs int64) (open, high, low, close, vol []float64)"
|
||||
description: "Agrega datos de ticks en velas OHLCV segun un intervalo de tiempo en segundos."
|
||||
tags: [finance, ohlcv, aggregate, tick]
|
||||
uses_functions: []
|
||||
uses_types: [tick_go_finance, ohlcv_go_finance]
|
||||
returns: [ohlcv_go_finance]
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/tick_to_ohlcv.go"
|
||||
---
|
||||
|
||||
# tick_to_ohlcv
|
||||
|
||||
Agrega ticks (precio, volumen, timestamp) en velas OHLCV. Los ticks se agrupan en buckets de `intervalSecs` segundos. Los timestamps deben estar en unix seconds y ordenados cronologicamente.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
o, h, l, c, v := finance.TickToOHLCV(
|
||||
[]float64{100, 101, 99, 102},
|
||||
[]float64{10, 20, 15, 25},
|
||||
[]int64{1000, 1005, 1055, 1060},
|
||||
60,
|
||||
)
|
||||
// Genera 2 velas: [1000-1059] y [1060-1119]
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
package finance
|
||||
|
||||
// VWAP calcula el Volume Weighted Average Price.
|
||||
// prices y volumes deben tener la misma longitud.
|
||||
// Retorna 0 si el volumen total es 0 o los slices estan vacios.
|
||||
func VWAP(prices, volumes []float64) float64 {
|
||||
if len(prices) == 0 || len(prices) != len(volumes) {
|
||||
return 0
|
||||
}
|
||||
var cumPV, cumV float64
|
||||
for i := range prices {
|
||||
cumPV += prices[i] * volumes[i]
|
||||
cumV += volumes[i]
|
||||
}
|
||||
if cumV == 0 {
|
||||
return 0
|
||||
}
|
||||
return cumPV / cumV
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: vwap
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func VWAP(prices, volumes []float64) float64"
|
||||
description: "Calcula el Volume Weighted Average Price (VWAP) a partir de precios y volumenes."
|
||||
tags: [finance, indicator, vwap, volume]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/vwap.go"
|
||||
---
|
||||
|
||||
# vwap
|
||||
|
||||
Calcula el VWAP (Volume Weighted Average Price). Es la suma de (precio * volumen) dividida por la suma de volumenes.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
v := finance.VWAP([]float64{100, 102, 101}, []float64{500, 300, 200})
|
||||
// v = (100*500 + 102*300 + 101*200) / (500+300+200)
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
package finance
|
||||
|
||||
import "fmt"
|
||||
|
||||
// WriteOHLCVToParquet persiste datos OHLCV en un archivo Parquet.
|
||||
// TODO: implementar escritura real usando libreria Parquet.
|
||||
func WriteOHLCVToParquet(path string, data [][]float64) error {
|
||||
return fmt.Errorf("not implemented: WriteOHLCVToParquet(%s)", path)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: write_ohlcv_to_parquet
|
||||
kind: function
|
||||
lang: go
|
||||
domain: finance
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func WriteOHLCVToParquet(path string, data [][]float64) error"
|
||||
description: "Persiste datos OHLCV en un archivo Parquet en la ruta indicada."
|
||||
tags: [finance, io, parquet, persist]
|
||||
uses_functions: []
|
||||
uses_types: [ohlcv_go_finance]
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [fmt]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "functions/finance/write_ohlcv_to_parquet.go"
|
||||
---
|
||||
|
||||
# write_ohlcv_to_parquet
|
||||
|
||||
Stub para persistir datos OHLCV en formato Parquet. Pendiente de implementacion.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
err := finance.WriteOHLCVToParquet("/data/btc_1h.parquet", ohlcvData)
|
||||
```
|
||||
Reference in New Issue
Block a user