dev.md 是 v1 设计稿但路线图已与 README 冲突;加废弃声明 + 优先级表,
指向 README / AGENTS / ai/adr 作为权威来源。AGENTS §2 与 harness-health
同步 v2.x 进度(Bollinger / Vegas / derivatives signal ✅;per-interval
完整化 + 箱体 + CI 未完)。README 路线图分段 v2.0/v2.x/v3,与 G12 守卫
扩白名单(derivatives_signal.go)保持一致。
1344 lines
25 KiB
Markdown
1344 lines
25 KiB
Markdown
> **⚠️ 部分废弃声明(2026-05-25)**
|
||
>
|
||
> 本文档是 v1 初始设计稿,保留下来主要是为了"为什么这么选"的历史与上下文。**对路线图、当前状态、阶段范围的判断不再以本文为准**。
|
||
>
|
||
> | 主题 | 以谁为准 |
|
||
> |---|---|
|
||
> | 当前版本 / 路线图 | `README.md` 末尾 "路线图" 段 |
|
||
> | 当前进行中的阶段与已完成 milestone | `AGENTS.md` §2 "当前状态" |
|
||
> | harness 工程健康度与未完事项 | `ai/harness-health.md` |
|
||
> | 架构与精度边界决策 | `ai/adr/0001-*.md`、`ai/adr/0002-*.md` |
|
||
> | 守卫规则 | `ai/risk-guardrails.md`(G1–G13) |
|
||
>
|
||
> 第 19 章("v2: CoinGlass / v3: ETF Flow / v4: CME")与 README 路线图(v2.x = MA/Bollinger/Vegas/箱体;v3 = CoinGlass + ETF + CME + …)**冲突,以 README 为准**。
|
||
>
|
||
> 其余章节(数据模型、Binance 字段解析、SQL schema 设计、Clean Arch 分层动机)仍有参考价值,可作为设计源头阅读,但需自行用代码与 ADR 校核是否仍现状成立。
|
||
|
||
---
|
||
|
||
# Hermes Market Data Gateway 开发文档
|
||
|
||
## 1. 项目目标
|
||
|
||
本项目用于给 Hermes 提供统一的币圈行情与衍生品分析上下文。
|
||
|
||
核心原则:
|
||
|
||
```text
|
||
1. Hermes 只调用本服务,不直接访问 Binance / CoinGlass / ETF 数据源
|
||
2. 本服务只提供市场数据与分析上下文,不做交易、不下单、不托管资金
|
||
3. 第一版只保留 REST API,不引入 gRPC / NATS / RabbitMQ
|
||
4. usecase 只依赖接口,不直接依赖 Binance client
|
||
5. Binance / CoinGlass / ETF / Macro / CME 都放在 repo/webapi
|
||
6. PostgreSQL / TimescaleDB 放在 repo/persistent
|
||
7. K线、Funding、OI、多空比长期数据必须落库
|
||
```
|
||
|
||
项目架构参考 `go-clean-template` 的 Clean Architecture 思路:业务逻辑放在 usecase,外部系统通过 repo/webapi 或 repo/persistent 实现接口,避免服务变大后 controller、client、DB 逻辑混在一起。该模板本身定位就是 Go 服务的 Clean Architecture 模板,并支持 REST、gRPC、AMQP RPC、NATS RPC 等 transport;本项目第一版只启用 REST。([GitHub][1])
|
||
|
||
---
|
||
|
||
## 2. 第一版范围
|
||
|
||
### 2.1 必须实现
|
||
|
||
第一版只做 Binance Futures 基础数据。
|
||
|
||
```text
|
||
数据源:
|
||
- Binance USDⓈ-M Futures Public API
|
||
|
||
币种:
|
||
- BTCUSDT
|
||
- ETHUSDT
|
||
|
||
周期:
|
||
- 15m
|
||
- 1h
|
||
- 4h
|
||
- 1d
|
||
- 1w
|
||
|
||
数据:
|
||
- K线 / OHLCV
|
||
- 24h ticker
|
||
- 当前 funding
|
||
- 历史 funding
|
||
- 当前 OI
|
||
- 历史 OI
|
||
- Global long/short ratio
|
||
- Top trader position ratio
|
||
- Taker buy/sell volume
|
||
```
|
||
|
||
Binance K线接口为 `GET /fapi/v1/klines`,K线由 open time 唯一标识,limit 默认 500、最大 1500;24h ticker 接口为 `GET /fapi/v1/ticker/24hr`,返回 lastPrice、highPrice、lowPrice、volume、quoteVolume、priceChangePercent 等字段。([Binance Developer Center][2])
|
||
|
||
Funding 历史接口为 `GET /fapi/v1/fundingRate`,limit 最大 1000;当前 OI 接口为 `GET /fapi/v1/openInterest`,历史 OI 接口为 `GET /futures/data/openInterestHist`,并且 Binance 官方说明历史 OI 只提供最近 1 个月数据,所以必须自己长期落库。([Binance Developer Center][3])
|
||
|
||
Long/Short Ratio 接口为 `GET /futures/data/globalLongShortAccountRatio`,官方说明只保留最近 30 天数据,也需要定时采集入库。([Binance Developer Center][4])
|
||
|
||
---
|
||
|
||
## 3. 非目标
|
||
|
||
第一版不做:
|
||
|
||
```text
|
||
1. 不做下单
|
||
2. 不做账户资产查询
|
||
3. 不接私有 API Key
|
||
4. 不做交易信号自动执行
|
||
5. 不做 NATS / RabbitMQ / gRPC
|
||
6. 不做复杂权限系统
|
||
7. 不做多租户
|
||
8. 不做清算热力图
|
||
9. 不做 CVD
|
||
10. 不做链上数据
|
||
```
|
||
|
||
后续版本再接:
|
||
|
||
```text
|
||
v2:
|
||
- CoinGlass
|
||
- ETF Flow
|
||
- 清算数据
|
||
- CME 缺口
|
||
|
||
v3:
|
||
- CVD
|
||
- 链上稳定币流动性
|
||
- 宏观日历
|
||
- 多交易所聚合
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 技术栈
|
||
|
||
```text
|
||
Language:
|
||
- Go 1.22+
|
||
|
||
HTTP:
|
||
- Gin 或 Fiber
|
||
- 如果你想贴近 go-clean-template,可以用 Fiber
|
||
|
||
Database:
|
||
- PostgreSQL
|
||
- TimescaleDB 可选,但推荐
|
||
|
||
Cache:
|
||
- Redis,可选
|
||
|
||
Scheduler:
|
||
- robfig/cron
|
||
|
||
DB Driver:
|
||
- pgx
|
||
|
||
Config:
|
||
- cleanenv 或 viper
|
||
|
||
Decimal:
|
||
- 推荐 shopspring/decimal
|
||
- 不建议用 float64 直接处理价格和成交量
|
||
```
|
||
|
||
推荐依赖:
|
||
|
||
```bash
|
||
go get github.com/gofiber/fiber/v2
|
||
go get github.com/jackc/pgx/v5/pgxpool
|
||
go get github.com/robfig/cron/v3
|
||
go get github.com/shopspring/decimal
|
||
go get github.com/ilyakaznacheev/cleanenv
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 项目目录结构
|
||
|
||
```text
|
||
crypto-hermes-gateway/
|
||
cmd/
|
||
app/
|
||
main.go
|
||
|
||
config/
|
||
config.go
|
||
config.yml
|
||
|
||
internal/
|
||
app/
|
||
app.go
|
||
scheduler.go
|
||
|
||
controller/
|
||
restapi/
|
||
router.go
|
||
middleware.go
|
||
v1/
|
||
market_routes.go
|
||
health_routes.go
|
||
|
||
entity/
|
||
kline.go
|
||
ticker.go
|
||
funding.go
|
||
open_interest.go
|
||
long_short_ratio.go
|
||
taker_volume.go
|
||
market_context.go
|
||
technical_level.go
|
||
|
||
usecase/
|
||
ports.go
|
||
market_context.go
|
||
market_collector.go
|
||
indicator.go
|
||
|
||
repo/
|
||
webapi/
|
||
binance/
|
||
client.go
|
||
dto.go
|
||
mapper.go
|
||
market.go
|
||
derivatives.go
|
||
|
||
persistent/
|
||
postgres/
|
||
kline_repo.go
|
||
funding_repo.go
|
||
open_interest_repo.go
|
||
long_short_ratio_repo.go
|
||
taker_volume_repo.go
|
||
|
||
worker/
|
||
collector.go
|
||
kline_collector.go
|
||
derivatives_collector.go
|
||
|
||
migrations/
|
||
000001_market_klines.up.sql
|
||
000001_market_klines.down.sql
|
||
000002_funding_rates.up.sql
|
||
000003_open_interest.up.sql
|
||
000004_long_short_ratio.up.sql
|
||
000005_taker_volume.up.sql
|
||
|
||
pkg/
|
||
httpclient/
|
||
client.go
|
||
logger/
|
||
logger.go
|
||
postgres/
|
||
postgres.go
|
||
|
||
docs/
|
||
development.md
|
||
api.md
|
||
database.md
|
||
|
||
docker-compose.yml
|
||
Dockerfile
|
||
Makefile
|
||
go.mod
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 分层说明
|
||
|
||
### 6.1 Controller 层
|
||
|
||
目录:
|
||
|
||
```text
|
||
internal/controller/restapi/v1
|
||
```
|
||
|
||
职责:
|
||
|
||
```text
|
||
1. 接收 HTTP 请求
|
||
2. 校验 query/path/body
|
||
3. 调用 usecase
|
||
4. 返回 JSON
|
||
```
|
||
|
||
禁止:
|
||
|
||
```text
|
||
1. 不直接调用 Binance client
|
||
2. 不写复杂业务逻辑
|
||
3. 不直接拼数据库 SQL
|
||
4. 不计算技术指标
|
||
```
|
||
|
||
示例接口:
|
||
|
||
```http
|
||
GET /v1/market/context?symbol=BTCUSDT
|
||
GET /v1/market/klines?symbol=BTCUSDT&interval=1h&limit=300
|
||
GET /v1/market/snapshot?symbol=BTCUSDT
|
||
GET /v1/market/derivatives?symbol=BTCUSDT&period=1h
|
||
GET /v1/health
|
||
```
|
||
|
||
---
|
||
|
||
### 6.2 Entity 层
|
||
|
||
目录:
|
||
|
||
```text
|
||
internal/entity
|
||
```
|
||
|
||
职责:
|
||
|
||
```text
|
||
1. 定义核心业务模型
|
||
2. 不依赖 Gin / Fiber
|
||
3. 不依赖 Binance DTO
|
||
4. 不依赖 PostgreSQL row
|
||
```
|
||
|
||
示例:
|
||
|
||
```go
|
||
package entity
|
||
|
||
type Kline struct {
|
||
Source string `json:"source"`
|
||
Symbol string `json:"symbol"`
|
||
Interval string `json:"interval"`
|
||
OpenTime int64 `json:"openTime"`
|
||
CloseTime int64 `json:"closeTime"`
|
||
Open string `json:"open"`
|
||
High string `json:"high"`
|
||
Low string `json:"low"`
|
||
Close string `json:"close"`
|
||
Volume string `json:"volume"`
|
||
QuoteVolume string `json:"quoteVolume"`
|
||
TradeCount int64 `json:"tradeCount"`
|
||
TakerBuyBaseVolume string `json:"takerBuyBaseVolume"`
|
||
TakerBuyQuoteVolume string `json:"takerBuyQuoteVolume"`
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 6.3 Usecase 层
|
||
|
||
目录:
|
||
|
||
```text
|
||
internal/usecase
|
||
```
|
||
|
||
职责:
|
||
|
||
```text
|
||
1. 编排业务流程
|
||
2. 聚合不同数据源
|
||
3. 计算 Hermes 需要的市场上下文
|
||
4. 通过接口依赖 repo,不依赖具体 Binance client
|
||
```
|
||
|
||
核心 usecase:
|
||
|
||
```text
|
||
MarketContextUsecase:
|
||
- 构建 /v1/market/context 返回结果
|
||
|
||
MarketCollectorUsecase:
|
||
- 定时采集 K线、Funding、OI、多空比
|
||
|
||
IndicatorUsecase:
|
||
- 计算支撑压力、均线、布林、Vegas、箱体等
|
||
```
|
||
|
||
---
|
||
|
||
### 6.4 Repo WebAPI 层
|
||
|
||
目录:
|
||
|
||
```text
|
||
internal/repo/webapi
|
||
```
|
||
|
||
职责:
|
||
|
||
```text
|
||
1. 调外部 API
|
||
2. 处理 Binance / CoinGlass / ETF 的原始 response
|
||
3. 将外部 DTO 映射成 entity
|
||
```
|
||
|
||
第一版只实现:
|
||
|
||
```text
|
||
internal/repo/webapi/binance
|
||
```
|
||
|
||
后续扩展:
|
||
|
||
```text
|
||
internal/repo/webapi/coinglass
|
||
internal/repo/webapi/etf
|
||
internal/repo/webapi/macro
|
||
internal/repo/webapi/cme
|
||
```
|
||
|
||
---
|
||
|
||
### 6.5 Repo Persistent 层
|
||
|
||
目录:
|
||
|
||
```text
|
||
internal/repo/persistent/postgres
|
||
```
|
||
|
||
职责:
|
||
|
||
```text
|
||
1. 落库
|
||
2. 查询历史数据
|
||
3. Upsert 去重
|
||
4. 提供给 usecase 使用的仓储接口实现
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Usecase 接口设计
|
||
|
||
`internal/usecase/ports.go`
|
||
|
||
```go
|
||
package usecase
|
||
|
||
import (
|
||
"context"
|
||
|
||
"crypto-hermes-gateway/internal/entity"
|
||
)
|
||
|
||
type MarketDataProvider interface {
|
||
GetKlines(ctx context.Context, symbol, interval string, limit int) ([]entity.Kline, error)
|
||
GetTicker24h(ctx context.Context, symbol string) (*entity.Ticker24h, error)
|
||
}
|
||
|
||
type DerivativesProvider interface {
|
||
GetCurrentFunding(ctx context.Context, symbol string) (*entity.FundingRate, error)
|
||
GetFundingHistory(ctx context.Context, symbol string, limit int) ([]entity.FundingRate, error)
|
||
|
||
GetCurrentOpenInterest(ctx context.Context, symbol string) (*entity.OpenInterest, error)
|
||
GetOpenInterestHistory(ctx context.Context, symbol, period string, limit int) ([]entity.OpenInterest, error)
|
||
|
||
GetGlobalLongShortRatio(ctx context.Context, symbol, period string, limit int) ([]entity.LongShortRatio, error)
|
||
GetTopTraderPositionRatio(ctx context.Context, symbol, period string, limit int) ([]entity.LongShortRatio, error)
|
||
|
||
GetTakerBuySellVolume(ctx context.Context, symbol, period string, limit int) ([]entity.TakerBuySellVolume, error)
|
||
}
|
||
|
||
type KlineRepository interface {
|
||
UpsertMany(ctx context.Context, items []entity.Kline) error
|
||
FindRecent(ctx context.Context, symbol, interval string, limit int) ([]entity.Kline, error)
|
||
}
|
||
|
||
type FundingRepository interface {
|
||
UpsertMany(ctx context.Context, items []entity.FundingRate) error
|
||
FindRecent(ctx context.Context, symbol string, limit int) ([]entity.FundingRate, error)
|
||
}
|
||
|
||
type OpenInterestRepository interface {
|
||
UpsertMany(ctx context.Context, items []entity.OpenInterest) error
|
||
FindRecent(ctx context.Context, symbol, period string, limit int) ([]entity.OpenInterest, error)
|
||
}
|
||
|
||
type LongShortRatioRepository interface {
|
||
UpsertMany(ctx context.Context, items []entity.LongShortRatio) error
|
||
FindRecent(ctx context.Context, symbol, period, ratioType string, limit int) ([]entity.LongShortRatio, error)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 核心聚合接口
|
||
|
||
### 8.1 Hermes 主接口
|
||
|
||
```http
|
||
GET /v1/market/context?symbol=BTCUSDT
|
||
```
|
||
|
||
用途:
|
||
|
||
```text
|
||
Hermes 分析 BTC / ETH 时,只调用这个接口。
|
||
```
|
||
|
||
返回结构:
|
||
|
||
```json
|
||
{
|
||
"symbol": "BTCUSDT",
|
||
"generatedAt": 1710000000000,
|
||
"snapshot": {
|
||
"lastPrice": "108000.12",
|
||
"priceChangePercent": "2.14",
|
||
"highPrice": "109200.00",
|
||
"lowPrice": "104800.00",
|
||
"volume": "123456.78",
|
||
"quoteVolume": "13200000000.00"
|
||
},
|
||
"klines": {
|
||
"15m": [],
|
||
"1h": [],
|
||
"4h": [],
|
||
"1d": [],
|
||
"1w": []
|
||
},
|
||
"derivatives": {
|
||
"funding": {
|
||
"current": {},
|
||
"history": []
|
||
},
|
||
"openInterest": {
|
||
"current": {},
|
||
"history": []
|
||
},
|
||
"longShortRatio": {
|
||
"global": [],
|
||
"topTraderPosition": []
|
||
},
|
||
"takerBuySellVolume": []
|
||
},
|
||
"technical": {
|
||
"support": [],
|
||
"resistance": [],
|
||
"rangeHigh": null,
|
||
"rangeLow": null,
|
||
"longShortLine": null
|
||
},
|
||
"dataQuality": {
|
||
"source": "binance",
|
||
"warnings": []
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Binance WebAPI 实现规范
|
||
|
||
### 9.1 Base URL
|
||
|
||
```text
|
||
https://fapi.binance.com
|
||
```
|
||
|
||
### 9.2 必接接口
|
||
|
||
```text
|
||
K线:
|
||
GET /fapi/v1/klines
|
||
|
||
24h ticker:
|
||
GET /fapi/v1/ticker/24hr
|
||
|
||
当前 funding:
|
||
GET /fapi/v1/premiumIndex
|
||
|
||
历史 funding:
|
||
GET /fapi/v1/fundingRate
|
||
|
||
当前 OI:
|
||
GET /fapi/v1/openInterest
|
||
|
||
历史 OI:
|
||
GET /futures/data/openInterestHist
|
||
|
||
全局多空比:
|
||
GET /futures/data/globalLongShortAccountRatio
|
||
|
||
大户持仓多空比:
|
||
GET /futures/data/topLongShortPositionRatio
|
||
|
||
主动买卖量:
|
||
GET /futures/data/takerlongshortRatio
|
||
```
|
||
|
||
### 9.3 HTTP Client 要求
|
||
|
||
```text
|
||
1. timeout: 10s
|
||
2. retry: 最多 2 次
|
||
3. retry only:
|
||
- 429
|
||
- 500
|
||
- 502
|
||
- 503
|
||
- 504
|
||
4. 所有请求带 context
|
||
5. 所有外部 API error 必须包装 source、path、status code
|
||
```
|
||
|
||
错误格式:
|
||
|
||
```go
|
||
type ExternalAPIError struct {
|
||
Source string
|
||
Path string
|
||
StatusCode int
|
||
Message string
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 10. 数据库设计
|
||
|
||
### 10.1 market_klines
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS market_klines (
|
||
source TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
interval TEXT NOT NULL,
|
||
|
||
open_time BIGINT NOT NULL,
|
||
close_time BIGINT NOT NULL,
|
||
|
||
open NUMERIC(36, 18) NOT NULL,
|
||
high NUMERIC(36, 18) NOT NULL,
|
||
low NUMERIC(36, 18) NOT NULL,
|
||
close NUMERIC(36, 18) NOT NULL,
|
||
|
||
volume NUMERIC(36, 18) NOT NULL,
|
||
quote_volume NUMERIC(36, 18) NOT NULL,
|
||
|
||
trade_count BIGINT NOT NULL,
|
||
|
||
taker_buy_base_volume NUMERIC(36, 18) NOT NULL,
|
||
taker_buy_quote_volume NUMERIC(36, 18) NOT NULL,
|
||
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
|
||
PRIMARY KEY (source, symbol, interval, open_time)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_market_klines_symbol_interval_time
|
||
ON market_klines(symbol, interval, open_time DESC);
|
||
```
|
||
|
||
---
|
||
|
||
### 10.2 funding_rates
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS funding_rates (
|
||
source TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
|
||
funding_time BIGINT NOT NULL,
|
||
funding_rate NUMERIC(36, 18) NOT NULL,
|
||
mark_price NUMERIC(36, 18),
|
||
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
|
||
PRIMARY KEY (source, symbol, funding_time)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_funding_rates_symbol_time
|
||
ON funding_rates(symbol, funding_time DESC);
|
||
```
|
||
|
||
---
|
||
|
||
### 10.3 open_interest
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS open_interest (
|
||
source TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
period TEXT NOT NULL,
|
||
|
||
timestamp BIGINT NOT NULL,
|
||
open_interest NUMERIC(36, 18) NOT NULL,
|
||
open_interest_value NUMERIC(36, 18),
|
||
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
|
||
PRIMARY KEY (source, symbol, period, timestamp)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_open_interest_symbol_period_time
|
||
ON open_interest(symbol, period, timestamp DESC);
|
||
```
|
||
|
||
---
|
||
|
||
### 10.4 long_short_ratio
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS long_short_ratio (
|
||
source TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
period TEXT NOT NULL,
|
||
ratio_type TEXT NOT NULL,
|
||
|
||
timestamp BIGINT NOT NULL,
|
||
|
||
long_short_ratio NUMERIC(36, 18) NOT NULL,
|
||
long_value NUMERIC(36, 18),
|
||
short_value NUMERIC(36, 18),
|
||
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
|
||
PRIMARY KEY (source, symbol, period, ratio_type, timestamp)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_long_short_ratio_symbol_period_time
|
||
ON long_short_ratio(symbol, period, ratio_type, timestamp DESC);
|
||
```
|
||
|
||
`ratio_type` 可选值:
|
||
|
||
```text
|
||
global_account
|
||
top_trader_position
|
||
top_trader_account
|
||
```
|
||
|
||
---
|
||
|
||
### 10.5 taker_buy_sell_volume
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS taker_buy_sell_volume (
|
||
source TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
period TEXT NOT NULL,
|
||
|
||
timestamp BIGINT NOT NULL,
|
||
|
||
buy_sell_ratio NUMERIC(36, 18),
|
||
buy_volume NUMERIC(36, 18),
|
||
sell_volume NUMERIC(36, 18),
|
||
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
|
||
PRIMARY KEY (source, symbol, period, timestamp)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_taker_buy_sell_symbol_period_time
|
||
ON taker_buy_sell_volume(symbol, period, timestamp DESC);
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 定时采集设计
|
||
|
||
### 11.1 支持币种
|
||
|
||
配置文件:
|
||
|
||
```yaml
|
||
symbols:
|
||
- BTCUSDT
|
||
- ETHUSDT
|
||
|
||
intervals:
|
||
- 15m
|
||
- 1h
|
||
- 4h
|
||
- 1d
|
||
- 1w
|
||
```
|
||
|
||
---
|
||
|
||
### 11.2 采集频率
|
||
|
||
```text
|
||
K线:
|
||
- 15m: 每 15 分钟采集一次
|
||
- 1h: 每小时采集一次
|
||
- 4h: 每 4 小时采集一次
|
||
- 1d: 每天采集一次
|
||
- 1w: 每周采集一次
|
||
|
||
Ticker:
|
||
- 30s 或 60s 刷新,可先不落库
|
||
|
||
Funding:
|
||
- 当前 funding: 每 15 分钟
|
||
- 历史 funding: 每 8 小时后补一次
|
||
|
||
OI:
|
||
- 当前 OI: 每 5 分钟或 15 分钟
|
||
- 历史 OI: 每 15 分钟
|
||
|
||
Long/Short Ratio:
|
||
- 每 15 分钟或 1 小时
|
||
|
||
Taker Buy/Sell:
|
||
- 每 15 分钟或 1 小时
|
||
```
|
||
|
||
---
|
||
|
||
### 11.3 Collector 设计
|
||
|
||
```go
|
||
type Collector struct {
|
||
marketData usecase.MarketDataProvider
|
||
derivatives usecase.DerivativesProvider
|
||
|
||
klineRepo usecase.KlineRepository
|
||
fundingRepo usecase.FundingRepository
|
||
oiRepo usecase.OpenInterestRepository
|
||
lsRepo usecase.LongShortRatioRepository
|
||
|
||
symbols []string
|
||
intervals []string
|
||
}
|
||
```
|
||
|
||
核心方法:
|
||
|
||
```go
|
||
func (c *Collector) CollectKlines(ctx context.Context) error
|
||
func (c *Collector) CollectFunding(ctx context.Context) error
|
||
func (c *Collector) CollectOpenInterest(ctx context.Context) error
|
||
func (c *Collector) CollectLongShortRatio(ctx context.Context) error
|
||
```
|
||
|
||
---
|
||
|
||
## 12. MarketContextUsecase 设计
|
||
|
||
### 12.1 构造方法
|
||
|
||
```go
|
||
type MarketContextUsecase struct {
|
||
marketData MarketDataProvider
|
||
derivatives DerivativesProvider
|
||
|
||
klineRepo KlineRepository
|
||
fundingRepo FundingRepository
|
||
oiRepo OpenInterestRepository
|
||
lsRepo LongShortRatioRepository
|
||
}
|
||
|
||
func NewMarketContextUsecase(
|
||
marketData MarketDataProvider,
|
||
derivatives DerivativesProvider,
|
||
klineRepo KlineRepository,
|
||
fundingRepo FundingRepository,
|
||
oiRepo OpenInterestRepository,
|
||
lsRepo LongShortRatioRepository,
|
||
) *MarketContextUsecase {
|
||
return &MarketContextUsecase{
|
||
marketData: marketData,
|
||
derivatives: derivatives,
|
||
klineRepo: klineRepo,
|
||
fundingRepo: fundingRepo,
|
||
oiRepo: oiRepo,
|
||
lsRepo: lsRepo,
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 12.2 Build 流程
|
||
|
||
```text
|
||
输入:
|
||
- symbol
|
||
|
||
流程:
|
||
1. 校验 symbol
|
||
2. 并发获取 snapshot / funding / current OI
|
||
3. 从 DB 获取 15m / 1h / 4h / 1d / 1w K线
|
||
4. 如果 DB 数据不足,则回源 Binance
|
||
5. 从 DB 获取 funding history
|
||
6. 从 DB 获取 OI history
|
||
7. 从 DB 获取 long/short ratio
|
||
8. 计算技术结构
|
||
9. 返回 Hermes MarketContext
|
||
```
|
||
|
||
---
|
||
|
||
## 13. API 设计
|
||
|
||
### 13.1 Health Check
|
||
|
||
```http
|
||
GET /v1/health
|
||
```
|
||
|
||
Response:
|
||
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"time": 1710000000000
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 13.2 Market Context
|
||
|
||
```http
|
||
GET /v1/market/context?symbol=BTCUSDT
|
||
```
|
||
|
||
Query:
|
||
|
||
```text
|
||
symbol: required, example BTCUSDT
|
||
```
|
||
|
||
Response:
|
||
|
||
```json
|
||
{
|
||
"symbol": "BTCUSDT",
|
||
"generatedAt": 1710000000000,
|
||
"snapshot": {},
|
||
"klines": {},
|
||
"derivatives": {},
|
||
"technical": {},
|
||
"dataQuality": {
|
||
"source": "binance",
|
||
"warnings": []
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 13.3 Klines
|
||
|
||
```http
|
||
GET /v1/market/klines?symbol=BTCUSDT&interval=1h&limit=300
|
||
```
|
||
|
||
Query:
|
||
|
||
```text
|
||
symbol: required
|
||
interval: required, enum 15m/1h/4h/1d/1w
|
||
limit: optional, default 300, max 1000
|
||
```
|
||
|
||
---
|
||
|
||
### 13.4 Snapshot
|
||
|
||
```http
|
||
GET /v1/market/snapshot?symbol=BTCUSDT
|
||
```
|
||
|
||
---
|
||
|
||
### 13.5 Derivatives
|
||
|
||
```http
|
||
GET /v1/market/derivatives?symbol=BTCUSDT&period=1h
|
||
```
|
||
|
||
Response:
|
||
|
||
```json
|
||
{
|
||
"symbol": "BTCUSDT",
|
||
"funding": {
|
||
"current": {},
|
||
"history": []
|
||
},
|
||
"openInterest": {
|
||
"current": {},
|
||
"history": []
|
||
},
|
||
"longShortRatio": {
|
||
"global": [],
|
||
"topTraderPosition": []
|
||
},
|
||
"takerBuySellVolume": [],
|
||
"warnings": []
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 14. 配置文件
|
||
|
||
`config/config.yml`
|
||
|
||
```yaml
|
||
app:
|
||
name: crypto-hermes-gateway
|
||
env: local
|
||
port: 8080
|
||
|
||
http:
|
||
read_timeout: 5s
|
||
write_timeout: 10s
|
||
idle_timeout: 60s
|
||
|
||
binance:
|
||
base_url: https://fapi.binance.com
|
||
timeout: 10s
|
||
retry_count: 2
|
||
|
||
postgres:
|
||
dsn: postgres://postgres:postgres@localhost:5432/hermes_market?sslmode=disable
|
||
max_conns: 10
|
||
min_conns: 2
|
||
|
||
collector:
|
||
enabled: true
|
||
symbols:
|
||
- BTCUSDT
|
||
- ETHUSDT
|
||
intervals:
|
||
- 15m
|
||
- 1h
|
||
- 4h
|
||
- 1d
|
||
- 1w
|
||
default_limit: 500
|
||
```
|
||
|
||
---
|
||
|
||
## 15. Docker Compose
|
||
|
||
```yaml
|
||
version: "3.9"
|
||
|
||
services:
|
||
postgres:
|
||
image: timescale/timescaledb:latest-pg16
|
||
container_name: hermes-postgres
|
||
environment:
|
||
POSTGRES_USER: postgres
|
||
POSTGRES_PASSWORD: postgres
|
||
POSTGRES_DB: hermes_market
|
||
ports:
|
||
- "5432:5432"
|
||
volumes:
|
||
- hermes_pg_data:/var/lib/postgresql/data
|
||
|
||
app:
|
||
build: .
|
||
container_name: hermes-market-gateway
|
||
depends_on:
|
||
- postgres
|
||
ports:
|
||
- "8080:8080"
|
||
environment:
|
||
CONFIG_PATH: /app/config/config.yml
|
||
volumes:
|
||
- ./config:/app/config
|
||
|
||
volumes:
|
||
hermes_pg_data:
|
||
```
|
||
|
||
---
|
||
|
||
## 16. Makefile
|
||
|
||
```makefile
|
||
run:
|
||
go run ./cmd/app
|
||
|
||
test:
|
||
go test ./...
|
||
|
||
lint:
|
||
golangci-lint run
|
||
|
||
docker-up:
|
||
docker compose up -d
|
||
|
||
docker-down:
|
||
docker compose down
|
||
|
||
migrate-up:
|
||
migrate -path ./migrations -database "$(DATABASE_URL)" up
|
||
|
||
migrate-down:
|
||
migrate -path ./migrations -database "$(DATABASE_URL)" down
|
||
```
|
||
|
||
---
|
||
|
||
## 17. Hermes 调用方式
|
||
|
||
Hermes 只调用:
|
||
|
||
```http
|
||
GET /v1/market/context?symbol=BTCUSDT
|
||
```
|
||
|
||
然后 Hermes prompt 使用:
|
||
|
||
```text
|
||
你是币圈量化分析引擎。请基于以下 JSON 市场上下文分析 BTCUSDT。
|
||
|
||
分析框架:
|
||
1. 多周期结构: 15m / 1h / 4h / 1d / 1w
|
||
2. 支撑压力: 前高、前低、箱体、成交密集区
|
||
3. 反弹质量: 量价、taker buy volume、OI、funding
|
||
4. 情绪拥挤: global long/short、top trader long/short
|
||
5. 判断是否诱多 / 诱空
|
||
6. 输出:
|
||
- 当前主方向
|
||
- 上方压力
|
||
- 下方支撑
|
||
- 多空分水岭
|
||
- 高空条件
|
||
- 低多条件
|
||
- 风险提示
|
||
|
||
市场上下文 JSON:
|
||
{{market_context_json}}
|
||
```
|
||
|
||
---
|
||
|
||
## 18. 开发里程碑
|
||
|
||
### Milestone 1:项目骨架
|
||
|
||
```text
|
||
目标:
|
||
- 基于 go-clean-template 思路搭建项目
|
||
- 删除 gRPC / NATS / RabbitMQ
|
||
- 保留 REST API
|
||
|
||
完成标准:
|
||
- GET /v1/health 返回 ok
|
||
- 项目可本地启动
|
||
```
|
||
|
||
---
|
||
|
||
### Milestone 2:Binance WebAPI
|
||
|
||
```text
|
||
目标:
|
||
- 实现 Binance client
|
||
- 实现 K线、ticker、funding、OI、多空比接口
|
||
|
||
完成标准:
|
||
- 可以成功请求 BTCUSDT / ETHUSDT
|
||
- 外部 API 错误有统一封装
|
||
- 不在 usecase 里直接依赖 Binance client
|
||
```
|
||
|
||
---
|
||
|
||
### Milestone 3:PostgreSQL 落库
|
||
|
||
```text
|
||
目标:
|
||
- 建表
|
||
- 实现 repository
|
||
- 支持 upsert
|
||
|
||
完成标准:
|
||
- K线可入库
|
||
- Funding 可入库
|
||
- OI 可入库
|
||
- Long/Short Ratio 可入库
|
||
```
|
||
|
||
---
|
||
|
||
### Milestone 4:定时采集
|
||
|
||
```text
|
||
目标:
|
||
- 实现 collector
|
||
- 定时采集 BTCUSDT / ETHUSDT
|
||
|
||
完成标准:
|
||
- 每 15 分钟采集 15m K线
|
||
- 每 1 小时采集 1h 级别数据
|
||
- 采集重复数据不会插入重复记录
|
||
```
|
||
|
||
---
|
||
|
||
### Milestone 5:Market Context API
|
||
|
||
```text
|
||
目标:
|
||
- 实现 Hermes 主接口
|
||
|
||
完成标准:
|
||
- GET /v1/market/context?symbol=BTCUSDT 返回完整 JSON
|
||
- 包含 snapshot、klines、funding、OI、多空比
|
||
- 数据不足时返回 dataQuality.warnings
|
||
```
|
||
|
||
---
|
||
|
||
### Milestone 6:技术结构计算
|
||
|
||
```text
|
||
目标:
|
||
- 初步计算支撑压力和趋势结构
|
||
|
||
完成标准:
|
||
- 返回 support
|
||
- 返回 resistance
|
||
- 返回 rangeHigh / rangeLow
|
||
- 返回 longShortLine
|
||
```
|
||
|
||
---
|
||
|
||
## 19. 后续扩展
|
||
|
||
### v2:CoinGlass
|
||
|
||
```text
|
||
新增:
|
||
- 清算统计
|
||
- 清算热力图
|
||
- 跨交易所 OI
|
||
- 跨交易所 funding
|
||
- ETF Flow
|
||
```
|
||
|
||
Binance WebSocket 强平流 `<symbol>@forceOrder` 只能推送每个 symbol 在 1000ms 内最大强平订单快照;如果要做清算密集区、热力图、清算地图,后续更适合接 CoinGlass / Hyblock 这类专业数据源。([Binance Developer Center][5])
|
||
|
||
---
|
||
|
||
### v3:ETF Flow
|
||
|
||
```text
|
||
新增:
|
||
- BTC ETF daily net flow
|
||
- ETH ETF daily net flow
|
||
- IBIT / FBTC / ARKB / BITB / GBTC 分项
|
||
- 最近 7 天 / 30 天净流入
|
||
```
|
||
|
||
---
|
||
|
||
### v4:宏观与 CME
|
||
|
||
```text
|
||
新增:
|
||
- CPI
|
||
- FOMC
|
||
- 非农
|
||
- 利率决议
|
||
- CME BTC Futures K线
|
||
- CME gap 自动计算
|
||
```
|
||
|
||
---
|
||
|
||
## 20. 验收标准
|
||
|
||
第一版验收标准:
|
||
|
||
```text
|
||
1. 服务可启动
|
||
2. /v1/health 正常
|
||
3. /v1/market/context?symbol=BTCUSDT 正常返回
|
||
4. /v1/market/context?symbol=ETHUSDT 正常返回
|
||
5. Binance client 不出现在 controller 中
|
||
6. usecase 只依赖接口
|
||
7. K线、Funding、OI、多空比已经落库
|
||
8. 采集任务可重复执行且不会产生重复数据
|
||
9. Hermes 只需要调用 /v1/market/context
|
||
10. 没有任何下单、账户、私钥、API Key 相关逻辑
|
||
```
|
||
|
||
---
|
||
|
||
## 21. 推荐开发顺序
|
||
|
||
```text
|
||
第 1 步:
|
||
搭项目骨架,跑通 /v1/health
|
||
|
||
第 2 步:
|
||
实现 Binance client + DTO mapper
|
||
|
||
第 3 步:
|
||
实现 usecase ports
|
||
|
||
第 4 步:
|
||
实现 /v1/market/klines 和 /v1/market/snapshot
|
||
|
||
第 5 步:
|
||
实现数据库 migration 和 repository
|
||
|
||
第 6 步:
|
||
实现 collector 定时落库
|
||
|
||
第 7 步:
|
||
实现 /v1/market/derivatives
|
||
|
||
第 8 步:
|
||
实现 /v1/market/context
|
||
|
||
第 9 步:
|
||
接 Hermes
|
||
|
||
第 10 步:
|
||
补技术指标和支撑压力计算
|
||
```
|
||
|
||
---
|
||
|
||
## 22. 最小可运行版本定义
|
||
|
||
MVP 只需要这一个接口稳定:
|
||
|
||
```http
|
||
GET /v1/market/context?symbol=BTCUSDT
|
||
```
|
||
|
||
只要它返回:
|
||
|
||
```text
|
||
1. 15m / 1h / 4h / 1d / 1w K线
|
||
2. 当前价格
|
||
3. 24h 涨跌幅
|
||
4. 24h 成交量
|
||
5. funding
|
||
6. OI
|
||
7. global long/short ratio
|
||
8. top trader position ratio
|
||
9. taker buy/sell volume
|
||
```
|
||
|
||
Hermes 就可以开始做“加密仲达系统”第一版分析。
|
||
|
||
[1]: https://github.com/evrone/go-clean-template?utm_source=chatgpt.com "GitHub - evrone/go-clean-template: Clean Architecture template for ..."
|
||
[2]: https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Kline-Candlestick-Data?utm_source=chatgpt.com "Kline Candlestick Data | Binance Open Platform"
|
||
[3]: https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Get-Funding-Rate-History "Get Funding Rate History | Binance Open Platform"
|
||
[4]: https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Long-Short-Ratio "Long Short Ratio | Binance Open Platform"
|
||
[5]: https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Liquidation-Order-Streams?utm_source=chatgpt.com "Liquidation Order Streams | Binance Open Platform"
|