按 ADR-0003 把 Support / Resistance / Range / LSLine 从顶层下沉进 IntervalTechnicals,每个周期独立计算;顶层 5 字段保留为 Intervals[primary] 镜像(单一来源,不双写)以维持向后兼容的 JSON shape。 新增 BoxBreak(Donchian 风格,lookback=20 根不含当前根,K 线 < 21 → nil), 落到 IntervalTechnicals.Box。 IndicatorComputer.Compute 签名升级到 longShortByInterval map: market_context 改为并发拉取 15m/1h/4h/1d 的全局 LSR,1w 不在 Binance LSR 支持列表 → 加 warning lsr_unsupported_interval:1w。 测试:boxBreak 6 个 case(inside/break_up/break_down/insufficient/2 个 parse 失败)+ per-interval Support/Resistance/Range 跨周期断言 + 镜像不变量 + 缺 LSR key → LongShortLine nil。indicator.go 平均覆盖 97.26%(boxBreak 100%)。
93 lines
4.0 KiB
Go
93 lines
4.0 KiB
Go
package usecase
|
||
|
||
import (
|
||
"context"
|
||
|
||
"cryptoHermes/internal/entity"
|
||
)
|
||
|
||
type MarketDataProvider interface {
|
||
GetKlines(ctx context.Context, symbol, interval string, limit int) ([]entity.Kline, error)
|
||
GetKlinesRange(ctx context.Context, symbol, interval string, startMs, endMs int64, 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)
|
||
}
|
||
|
||
type TakerVolumeRepository interface {
|
||
UpsertMany(ctx context.Context, items []entity.TakerBuySellVolume) error
|
||
FindRecent(ctx context.Context, symbol, period string, limit int) ([]entity.TakerBuySellVolume, error)
|
||
}
|
||
|
||
// IndicatorComputer 纯函数式接口:接收已经被上层 fetch 的 slice,
|
||
// 返回填充好的 TechnicalStructure。
|
||
//
|
||
// 不持有任何 repo 引用——保住 G1(usecase 不依赖 repo 实现)和
|
||
// G12(indicator 包零 repo 导入)。MarketContextUsecase 已经并发 fetch
|
||
// 过 kline 与 long-short ratio,复用结果即可,二次注入仓库引用会
|
||
// 重复 IO。
|
||
//
|
||
// klinesByInterval 是按周期分组的 K 线 map(每周期一份升序切片);
|
||
// primaryInterval 决定顶层 TechnicalStructure 镜像哪个周期;所有周期
|
||
// 都会独立填充进 Intervals。longShortByInterval 按周期分组的 LSR map
|
||
// (某周期缺失时,该周期 IntervalTechnicals.LongShortLine 为 nil)。
|
||
// 实现可见 internal/usecase/indicator.go。
|
||
type IndicatorComputer interface {
|
||
Compute(
|
||
klinesByInterval map[string][]entity.Kline,
|
||
primaryInterval string,
|
||
longShortByInterval map[string][]entity.LongShortRatio,
|
||
) entity.TechnicalStructure
|
||
}
|
||
|
||
// DerivativesSignalComputer 把 funding/OI/LSR 的原始数据翻译成
|
||
// 可读语义(crowded_long、long_building 之类)。
|
||
//
|
||
// 与 IndicatorComputer 一样是纯函数式接口、零 repo 依赖。
|
||
//
|
||
// primaryKlines 是用来给 OI 信号做"价格方向"判定的:OI 在涨时,配合
|
||
// 价格涨 → long_building,价格跌 → short_building(funding 不参与 OI
|
||
// 判定,避免价格下跌但 funding 仍为正时被误判)。
|
||
//
|
||
// 返回 warnings 用来告诉调用方"哪一项数据不够、对应字段为什么留空",
|
||
// 由调用方合并到 DataQuality.Warnings。signal 整体不可判时返回 nil。
|
||
type DerivativesSignalComputer interface {
|
||
Compute(
|
||
currentFunding *entity.FundingRate,
|
||
oiHistory []entity.OpenInterest,
|
||
globalLSR []entity.LongShortRatio,
|
||
primaryKlines []entity.Kline,
|
||
) (*entity.DerivativesSignal, []string)
|
||
}
|