From 9e90da5bdb77c01955583f34c097e6c46dba0683 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Sat, 1 Mar 2025 19:36:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=8B=89=E5=8F=96K=E7=BA=BF,?= =?UTF-8?q?=20=E5=B9=B6=E7=94=A8python=E6=9D=A5=E5=8F=AF=E8=A7=86=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + cache/cache.go | 1 + cmd/main.go | 181 +++++++++++++++++++------ collector/collector.go | 1 + config/config.go | 1 + config/config.yaml | 1 + feature_processor/feature_processor.go | 1 + go.mod | 25 ++++ go.sum | 86 ++++++++++++ python/plot_ohlcv.py | 54 ++++++++ scheduler/scheduler.go | 1 + storage/storage.go | 1 + 12 files changed, 317 insertions(+), 38 deletions(-) create mode 100644 .gitignore create mode 100644 config/config.go create mode 100644 python/plot_ohlcv.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7303d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor +cmd/cmd diff --git a/cache/cache.go b/cache/cache.go index e69de29..08bf029 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -0,0 +1 @@ +package cache diff --git a/cmd/main.go b/cmd/main.go index c98f64b..6cb71f2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,52 +2,157 @@ package main import ( "fmt" - "gitea.zjmud.xyz/phyer/blingo/cache" - "gitea.zjmud.xyz/phyer/blingo/collector" - "gitea.zjmud.xyz/phyer/blingo/config" - "gitea.zjmud.xyz/phyer/blingo/feature_processor" - "gitea.zjmud.xyz/phyer/blingo/scheduler" - "gitea.zjmud.xyz/phyer/blingo/storage" - "log" + // "gitea.zjmud.xyz/phyer/blingo/cache" + // "gitea.zjmud.xyz/phyer/blingo/collector" + // "gitea.zjmud.xyz/phyer/blingo/config" + // "gitea.zjmud.xyz/phyer/blingo/feature_processor" + // "gitea.zjmud.xyz/phyer/blingo/scheduler" + // "gitea.zjmud.xyz/phyer/blingo/storage" + // "log" + // "error" + ccxt "gitea.zjmud.xyz/ext/ccxt-go" + "os" + "os/exec" + // "net/http" + "time" ) func main() { - // 1. 加载配置 - cfg, err := config.LoadConfig("config/config.yaml") - if err != nil { - log.Fatalf("Error loading config: %v", err) - } - fmt.Println("Configuration loaded successfully.") - // 2. 数据采集 - data, err := collector.CollectData(cfg) - if err != nil { - log.Fatalf("Error collecting data: %v", err) - } - fmt.Println("Data collected successfully.") + // 1. 创建 OKX 交易所实例 + okx := ccxt.NewOkx(map[string]interface{}{ + "apiKey": "fe468418-5e40-433f-8d04-04951286d417", + "secret": "D6D74DF9DD60A25BE2B27CA71D8F814D", + "password": "M4pw71Id", + "hostname": "aws.okx.com", + }) - // 3. 特征处理 - processedData, err := feature_processor.ProcessFeatures(data) - if err != nil { - log.Fatalf("Error processing features: %v", err) - } - fmt.Println("Features processed successfully.") + // 3. 可选:自定义 HTTP 客户端配置 + // okx.HttpClient.Timeout = 15 * time.Second + okx.EnableRateLimit = true // 启用内置速率限制 - // 4. 缓存处理 - err = cache.CacheData(processedData) - if err != nil { - log.Fatalf("Error caching data: %v", err) + // 4. 加载市场数据(关键步骤!) + marketsChan := okx.LoadMarkets() + select { + case marketsResult := <-marketsChan: + switch v := marketsResult.(type) { + case error: + panic(fmt.Errorf("加载市场数据失败: %v", v)) + case string: + panic(fmt.Errorf("加载市场数据失败: %v", v)) + case map[string]interface{}: + okx.Markets = v + default: + panic(fmt.Errorf("加载市场数据失败: 未知类型的结果")) + } + case <-time.After(30 * time.Second): + panic(fmt.Errorf("加载市场数据超时")) } - fmt.Println("Data cached successfully.") - // 5. 存储数据 - err = storage.StoreData(processedData) - if err != nil { - log.Fatalf("Error storing data: %v", err) + fmt.Println("OKX 初始化完成,已加载", len(okx.Markets), "个交易对") + // 获取ticker数据 + symbol := "BTC/USDT" + // ticker, err := okx.FetchTicker(symbol) + // if err != nil { + // fmt.Println("获取ticker数据错误:", err) + // return + // } + // fmt.Println("ticker数据:", ticker) + + // 获取BTC/USDT的1分钟K线数据 + // 创建一个 FetchOHLCVOptionsStruct 实例 + // + // // 使用 WithFetchOHLCVTimeframe 设置时间框架 + // ccxt.WithFetchOHLCVTimeframe("1h")(opts) + // + // // 使用 WithFetchOHLCVSince 设置开始时间 + // ccxt.WithFetchOHLCVSince(1672531200)(opts) // 示例时间戳 + // + // // 使用 WithFetchOHLCVLimit 设置最大数量 + // ccxt.WithFetchOHLCVLimit(100)(opts) + + // 使用 WithFetchOHLCVParams 设置其他参数 + // params := map[string]interface{}{ + // "adjustForTimezone": true, + // "includeHighLow": false, + // } + // ccxt.WithFetchOHLCVParams(params)(opts) + + // 打印设置后的 opts + // fmt.Printf("%+v\n", opts) + + tf := "1h" + sc := int64(1672502400000) + lm := int64(1000) + pm := map[string]interface{}{ + "rateLimit": true, // Hypothetical parameter to enable rate limiting } - fmt.Println("Data stored successfully.") - // 6. 调度执行 - scheduler.ScheduleTasks(cfg) - fmt.Println("Tasks scheduled successfully.") + ohlcv, err := okx.FetchOHLCV(symbol, + ccxt.WithFetchOHLCVSince(sc), + ccxt.WithFetchOHLCVTimeframe(tf), + ccxt.WithFetchOHLCVLimit(lm), + ccxt.WithFetchOHLCVParams(pm)) + if err != nil { + fmt.Println("Error fetching OHLCV:", err) + return + } + fmt.Println("ohlcv: ", ohlcv) + // 检查并删除旧文件 + fileName := "ohlcv-btc.csv" + destName := "/tmp/blingo/python/" + fileName + if _, err := os.Stat(destName); err == nil { + // 文件存在,删除它 + if err := os.Remove(destName); err != nil { + fmt.Println("删除旧文件失败:", err) + return + } + } + + // 创建临时文件 + tmpFile, err := os.CreateTemp("", fileName) + if err != nil { + fmt.Println("创建临时文件失败:", err) + return + } + defer os.Remove(tmpFile.Name()) // 程序结束后删除临时文件 + + // 写入CSV数据 + for _, candle := range ohlcv { + line := fmt.Sprintf("%d,%.2f,%.2f,%.2f,%.2f,%.2f\n", + candle.Timestamp, // 时间戳 + candle.Open, // 开盘价 + candle.High, // 最高价 + candle.Low, // 最低价 + candle.Close, // 收盘价 + candle.Volume) // 成交量 + if _, err := tmpFile.WriteString(line); err != nil { + fmt.Println("写入文件失败:", err) + return + } + } + // 确保目标目录存在 + destDir := "/tmp/blingo/python/" + if err := os.MkdirAll(destDir, 0755); err != nil { + fmt.Println("创建目录失败:", err) + return + } + + // 重命名文件 + destName = destDir + fileName + if err := os.Rename(tmpFile.Name(), destName); err != nil { + fmt.Println("重命名文件失败:", err) + return + } + tmpFile.Close() + + // 调用Python脚本 + cmd := exec.Command("python3", "plot_ohlcv.py", destName) + cmd.Dir = "../python" // 设置工作目录 + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Println("执行Python脚本失败:", err) + return + } } diff --git a/collector/collector.go b/collector/collector.go index e69de29..ace15e3 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -0,0 +1 @@ +package conllector diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..d912156 --- /dev/null +++ b/config/config.go @@ -0,0 +1 @@ +package config diff --git a/config/config.yaml b/config/config.yaml index e69de29..8b13789 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -0,0 +1 @@ + diff --git a/feature_processor/feature_processor.go b/feature_processor/feature_processor.go index e69de29..95af6c9 100644 --- a/feature_processor/feature_processor.go +++ b/feature_processor/feature_processor.go @@ -0,0 +1 @@ +package processor diff --git a/go.mod b/go.mod index 41979ff..b8f6328 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,28 @@ module gitea.zjmud.xyz/phyer/blingo go 1.24.0 + +require gitea.zjmud.xyz/ext/ccxt-go v0.0.0-20250228023320-1a2ce7046aca + +require ( + github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/ethereum/go-ethereum v1.14.13 // indirect + github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/holiman/uint256 v1.3.1 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/supranational/blst v0.3.13 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.28.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/go.sum b/go.sum index e69de29..321f8d6 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,86 @@ +gitea.zjmud.xyz/ext/ccxt-go v0.0.0-20250228023320-1a2ce7046aca h1:Fud3kEl0BniVDNkbqvzUOP97AMSZSSXKBdNq/FW4aDU= +gitea.zjmud.xyz/ext/ccxt-go v0.0.0-20250228023320-1a2ce7046aca/go.mod h1:hj67W64XPTygOx5fdK3wlr+W1J74+5MRabzF79w7pUk= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.14.13 h1:L81Wmv0OUP6cf4CW6wtXsr23RUrDhKs2+Y9Qto+OgHU= +github.com/ethereum/go-ethereum v1.14.13/go.mod h1:RAC2gVMWJ6FkxSPESfbshrcKpIokgQKsVKmAuqdekDY= +github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= +github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= +github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= +github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/python/plot_ohlcv.py b/python/plot_ohlcv.py new file mode 100644 index 0000000..1b1f634 --- /dev/null +++ b/python/plot_ohlcv.py @@ -0,0 +1,54 @@ +import argparse +import matplotlib.pyplot as plt +from matplotlib.dates import DateFormatter, MinuteLocator +import pandas as pd +from datetime import datetime + +def parse_args(): + parser = argparse.ArgumentParser(description='OHLCV可视化工具') + parser.add_argument('file_path', type=str, help='OHLCV数据文件路径') + return parser.parse_args() + +def load_data(file_path): + """加载CSV格式的OHLCV数据""" + df = pd.read_csv(file_path, header=None, + names=['timestamp', 'open', 'high', 'low', 'close', 'volume']) + + # 转换时间戳为datetime + df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms') + return df + +def plot_candlestick(df): + """绘制K线图""" + fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), gridspec_kw={'height_ratios': [3,1]}) + + # 绘制K线 + for idx, row in df.iterrows(): + color = 'g' if row['close'] > row['open'] else 'r' + ax1.vlines(row['datetime'], row['low'], row['high'], color=color, linewidth=1) + ax1.vlines(row['datetime'], row['open'], row['close'], color=color, linewidth=3) + + # 设置时间格式 + date_format = DateFormatter('%m-%d %H:%M') + ax1.xaxis.set_major_formatter(date_format) + ax1.xaxis.set_major_locator(MinuteLocator(interval=30)) + ax1.set_title('OKX BTC/USDT 1小时K线图') + ax1.grid(True) + + # 绘制成交量 + ax2.bar(df['datetime'], df['volume'], color=[('g' if c > o else 'r') for c, o in zip(df['close'], df['open'])], width=0.002) + ax2.xaxis.set_major_formatter(date_format) + ax2.set_title('成交量') + ax2.grid(True) + + plt.tight_layout() + plt.show() + +if __name__ == "__main__": + args = parse_args() + try: + df = load_data(args.file_path) + plot_candlestick(df) + except Exception as e: + print(f"数据处理失败: {str(e)}") + diff --git a/scheduler/scheduler.go b/scheduler/scheduler.go index e69de29..6990da0 100644 --- a/scheduler/scheduler.go +++ b/scheduler/scheduler.go @@ -0,0 +1 @@ +package scheduler diff --git a/storage/storage.go b/storage/storage.go index e69de29..82be054 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -0,0 +1 @@ +package storage