114 lines
2.5 KiB
Go
114 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
// ================== Dataset ==================
|
|
|
|
type Dataset struct {
|
|
Seqs [][]float64
|
|
Labels []float64
|
|
Mean float64
|
|
Std float64
|
|
}
|
|
|
|
func buildDataset(kl []Kline, lookback int, valSplit float64) (Dataset, Dataset) {
|
|
if len(kl) < lookback+2 {
|
|
return Dataset{}, Dataset{}
|
|
}
|
|
prices := make([]float64, len(kl))
|
|
for i, k := range kl {
|
|
prices[i] = k.Close
|
|
}
|
|
logp := make([]float64, len(prices))
|
|
for i, p := range prices {
|
|
logp[i] = math.Log(p)
|
|
}
|
|
lr := make([]float64, len(logp)-1)
|
|
for i := 1; i < len(logp); i++ {
|
|
lr[i-1] = logp[i] - logp[i-1]
|
|
}
|
|
N := len(lr) - lookback
|
|
if N <= 0 {
|
|
return Dataset{}, Dataset{}
|
|
}
|
|
X := make([][]float64, 0, N)
|
|
Y := make([]float64, 0, N)
|
|
for i := 0; i < N; i++ {
|
|
win := make([]float64, lookback)
|
|
copy(win, lr[i:i+lookback])
|
|
X = append(X, win)
|
|
Y = append(Y, lr[i+lookback])
|
|
}
|
|
valN := int(float64(len(X)) * valSplit)
|
|
if valN < 1 {
|
|
valN = 1
|
|
}
|
|
trainN := len(X) - valN
|
|
mean, std := meanStd(flatten(X[:trainN]))
|
|
if std == 0 {
|
|
std = 1e-6
|
|
}
|
|
zX := make([][]float64, len(X))
|
|
for i := range X {
|
|
zX[i] = make([]float64, lookback)
|
|
for j := range X[i] {
|
|
zX[i][j] = (X[i][j] - mean) / std
|
|
}
|
|
}
|
|
zY := make([]float64, len(Y))
|
|
for i := range Y {
|
|
zY[i] = (Y[i] - mean) / std
|
|
}
|
|
train := Dataset{Seqs: zX[:trainN], Labels: zY[:trainN], Mean: mean, Std: std}
|
|
val := Dataset{Seqs: zX[trainN:], Labels: zY[trainN:], Mean: mean, Std: std}
|
|
return train, val
|
|
}
|
|
|
|
func flatten(x [][]float64) []float64 {
|
|
out := make([]float64, 0, len(x)*max(1, len(x[0])))
|
|
for _, r := range x {
|
|
out = append(out, r...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func meanStd(x []float64) (float64, float64) {
|
|
if len(x) == 0 {
|
|
return 0, 1
|
|
}
|
|
var m float64
|
|
for _, v := range x {
|
|
m += v
|
|
}
|
|
m /= float64(len(x))
|
|
var s float64
|
|
for _, v := range x {
|
|
d := v - m
|
|
s += d * d
|
|
}
|
|
s = math.Sqrt(s / float64(len(x)))
|
|
return m, s
|
|
}
|
|
|
|
func max(a, b int) int {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Istruzioni manuali + gestione stato (lock)
|
|
func printManualInstruction(fromLabel, toLabel string, amountFrom, expectedBps, feeBps, safetyBps float64) string {
|
|
fromS := assetShort(fromLabel)
|
|
toS := assetShort(toLabel)
|
|
maxFeeBps := expectedBps - safetyBps
|
|
if maxFeeBps < 0 {
|
|
maxFeeBps = 0
|
|
}
|
|
maxFeeAbs := amountFrom * (maxFeeBps / 1e4)
|
|
return fmt.Sprintf("ISTRUZIONI MANUALI: esegui swap %s->%s amount=%.8f; procedi solo se feeTotali<=%.3f bps (stima THOR=%.3f bps) e costo<=~%.8f %s", fromS, toS, amountFrom, maxFeeBps, feeBps, maxFeeAbs, fromS)
|
|
}
|