refactor: split large files and clean up project structure

- Rename experience/ to telemetry/ for clarity
- Split 15+ large Go files (800-2200 lines) into focused modules:
  kernel/engine.go, backtest/runner.go, market/data.go, store/position.go,
  api/handler_trader.go, trader/auto_trader_grid.go, and 9 exchange traders
- Split frontend monoliths: types.ts, api.ts, AITradersPage.tsx, BacktestPage.tsx
  into domain-specific modules with barrel re-exports
- Remove stale files: screenshots, .yml.old, pyproject.toml
- Remove unused scripts/ and cmd/ directories
- Remove broken/outdated test files (network-dependent, stale expectations)
This commit is contained in:
tinkle-community
2026-03-12 12:53:57 +08:00
parent 8e294a5eed
commit cb31782be4
113 changed files with 20423 additions and 25733 deletions
-35
View File
@@ -1,35 +0,0 @@
package alpaca
import (
"context"
"fmt"
"testing"
)
func TestGetBars(t *testing.T) {
client := NewClient()
resp, err := client.GetBars(context.TODO(), "AAPL", "1Day", 5)
if err != nil {
t.Fatal(err)
}
t.Log("=== AAPL 日线数据 (Alpaca IEX feed) ===")
for i, bar := range resp {
t.Logf("\n[%d] 时间: %s", i, bar.Timestamp.Format("2006-01-02 15:04:05"))
t.Logf(" Open: %.2f", bar.Open)
t.Logf(" High: %.2f", bar.High)
t.Logf(" Low: %.2f", bar.Low)
t.Logf(" Close: %.2f", bar.Close)
t.Logf(" Volume: %d (股数)", bar.Volume)
t.Logf(" TradeCount: %d (成交笔数)", bar.TradeCount)
t.Logf(" VWAP: %.2f (成交量加权平均价)", bar.VWAP)
// 计算成交额
quoteVolume := float64(bar.Volume) * bar.Close
t.Logf(" 成交额: %.2f USD (Volume × Close)", quoteVolume)
}
fmt.Printf("\n⚠️ 注意:IEX feed 只包含 IEX 交易所的数据,不是完整市场数据\n")
fmt.Printf("完整市场数据需要使用 SIP feed(付费)\n")
}
-34
View File
@@ -1,34 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"nofx/provider/coinank/coinank_enum"
"testing"
)
func TestListCoin(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.ListCoin(context.TODO(), "SPOT")
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestListSymbols(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.ListSymbols(context.TODO(), "Binance", "SWAP")
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
-3
View File
@@ -1,3 +0,0 @@
package coinank
var TestApikey = "" //need fill the apikey before test
@@ -1,101 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"nofx/provider/coinank/coinank_enum"
"testing"
)
func TestVisualScreener(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.VisualScreener(context.TODO(), coinank_enum.Minute15)
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestOiRank(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.OiRank(context.TODO(), coinank_enum.OpenInterest, coinank_enum.Desc, 1, 10)
if err != nil {
t.Error(err)
}
if resp[0].BaseCoin != "BTC" {
t.Error("oi first not BTC")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestLongShortRank(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LongShortRank(context.TODO(), coinank_enum.LongShortRatio, coinank_enum.Desc, 1, 10)
if err != nil {
t.Error(err)
}
if resp[0].BaseCoin == "" {
t.Error("baseCoin is empty")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestLiquidationRank(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LiquidationRank(context.TODO(), coinank_enum.LiquidationH1, coinank_enum.Desc, 1, 10)
if err != nil {
t.Error(err)
}
if resp[0].BaseCoin == "" {
t.Error("baseCoin is empty")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestPriceRank(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.PriceRank(context.TODO(), coinank_enum.Price, coinank_enum.Desc, 1, 10)
if err != nil {
t.Error(err)
}
if resp[0].BaseCoin == "" {
t.Error("baseCoin is empty")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestVolumeRank(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.VolumeRank(context.TODO(), coinank_enum.Turnover24h, coinank_enum.Desc, 1, 10)
if err != nil {
t.Error(err)
}
if resp[0].BaseCoin == "" {
t.Error("baseCoin is empty")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
-34
View File
@@ -1,34 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"nofx/provider/coinank/coinank_enum"
"testing"
)
func TestGetLastPrice(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.GetLastPrice(context.TODO(), "BTCUSDT", "Binance", "SWAP")
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestGetCoinMarketCap(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.GetCoinMarketCap(context.TODO(), "BTC")
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
-56
View File
@@ -1,56 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"fmt"
"nofx/provider/coinank/coinank_enum"
"testing"
"time"
)
func TestKline(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.Kline(context.TODO(), "BTCUSDT", coinank_enum.Binance, 0, time.Now().UnixMilli(), 10, coinank_enum.Hour1)
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestKlineDaily(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.Kline(context.TODO(), "BTCUSDT", coinank_enum.Binance, 0, time.Now().UnixMilli(), 5, coinank_enum.Day1)
if err != nil {
t.Fatal(err)
}
t.Log("=== BTCUSDT 日线 K线数据 ===")
for i, k := range resp {
startTime := time.UnixMilli(k.StartTime).Format("2006-01-02 15:04:05")
t.Logf("\n[%d] 时间: %s", i, startTime)
t.Logf(" Open: %.2f", k.Open)
t.Logf(" High: %.2f", k.High)
t.Logf(" Low: %.2f", k.Low)
t.Logf(" Close: %.2f", k.Close)
t.Logf(" Volume: %.2f (k[6])", k.Volume)
t.Logf(" Quantity: %.2f (k[7])", k.Quantity)
t.Logf(" Count: %.0f (k[8])", k.Count)
// 计算验证
if k.Close > 0 {
calcQuote := k.Volume * k.Close
t.Logf(" --- 验证 ---")
t.Logf(" Volume × Close = %.2f", calcQuote)
t.Logf(" Quantity / Close = %.2f", k.Quantity/k.Close)
}
}
// 打印原始 JSON
res, _ := json.MarshalIndent(resp, "", " ")
fmt.Printf("\n原始 JSON:\n%s\n", res)
}
-89
View File
@@ -1,89 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"nofx/provider/coinank/coinank_enum"
"testing"
"time"
)
func TestLiquidationExchangeStatistics(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LiquidationExchangeStatistics(context.TODO(), "BTC")
if err != nil {
t.Fatal(err)
}
if resp.Total <= 0 {
t.Errorf("total amount is negative")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestLiquidationCoinAggHistory(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LiquidationCoinAggHistory(context.TODO(), "BTC", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Fatal(err)
}
if resp[0].All.LongTurnover <= 0 {
t.Errorf("longTurnover is negative")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestLiquidationHistory(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LiquidationHistory(context.TODO(), coinank_enum.Binance, "BTCUSDT", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Fatal(err)
}
if resp[0].LongTurnover <= 0 {
t.Errorf("longTurnover is negative")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestLiquidationOrders(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LiquidationOrders(context.TODO(), "BTC", coinank_enum.Binance, "long", 1000, time.Now().UnixMilli())
if err != nil {
t.Fatal(err)
}
res, err := json.Marshal(resp)
if resp[0].Price <= 0 {
t.Errorf("price is negative")
}
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestLiquidationOrdersNoArgs(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.LiquidationOrders(context.TODO(), "", "", "", 0, 0)
if err != nil {
t.Fatal(err)
}
res, err := json.Marshal(resp)
if resp[0].Price <= 0 {
t.Errorf("price is negative")
}
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
-25
View File
@@ -1,25 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"nofx/provider/coinank/coinank_enum"
"testing"
"time"
)
func TestNetPositions(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.NetPositions(context.TODO(), coinank_enum.Binance, "BTCUSDT", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Fatal(err)
}
if resp[0].Begin <= 0 {
t.Errorf("begin timestamp error")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
-106
View File
@@ -1,106 +0,0 @@
package coinank
import (
"context"
"encoding/json"
"nofx/provider/coinank/coinank_enum"
"testing"
"time"
)
func TestOpenInterestAll(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.OpenInterestAll(context.TODO(), "BTC")
if err != nil {
t.Error(err)
}
if resp[0].ExchangeName != "ALL" {
t.Error("exchange name is empty")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestOpenInterestChartV2(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.OpenInterestChartV2(context.TODO(), "BTC", coinank_enum.Binance, coinank_enum.Hour1, 10)
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestOpenInterestSymbolChart(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.OpenInterestSymbolChart(context.TODO(), coinank_enum.Binance, "BTCUSDT", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Error(err)
}
if resp[0].BaseCoin != "BTC" {
t.Error("baseCoin is error")
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestOpenInterestKline(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.OpenInterestKline(context.TODO(), coinank_enum.Binance, "BTCUSDT", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestOpenInterestAggKline(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.OpenInterestAggKline(context.TODO(), "BTC", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestTickersTopOIByEx(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.TickersTopOIByEx(context.TODO(), "BTC")
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}
func TestInstrumentsOiVsMc(t *testing.T) {
client := NewCoinankClient(coinank_enum.MainUrl, TestApikey)
resp, err := client.InstrumentsOiVsMc(context.TODO(), "BTC", coinank_enum.Hour1, time.Now().UnixMilli(), 10)
if err != nil {
t.Error(err)
}
res, err := json.Marshal(resp)
if err != nil {
t.Error(err)
}
t.Logf("%s", res)
}