mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-09 14:00:57 +08:00
Add multi-timeframe data analysis support
Introduces 15m and 1h timeframes to Data struct and related calculations for more robust multi-timeframe analysis. Updates system prompt to reflect new data sources and analysis methods, and extends Format output to include mid-term series. Enhances signal quality and trend confirmation by leveraging multiple timeframes.
This commit is contained in:
@@ -279,20 +279,35 @@ func buildSystemPrompt(accountEquity float64, btcEthLeverage, altcoinLeverage in
|
||||
// === 开仓信号强度 ===
|
||||
sb.WriteString("# 🎯 开仓标准(严格)\n\n")
|
||||
sb.WriteString("只在**强信号**时开仓,不确定就观望。\n\n")
|
||||
sb.WriteString("**你拥有的完整数据**:\n")
|
||||
sb.WriteString("- 📊 **原始序列**:3分钟价格序列(MidPrices数组) + 4小时K线序列\n")
|
||||
sb.WriteString("- 📈 **技术序列**:EMA20序列、MACD序列、RSI7序列、RSI14序列\n")
|
||||
sb.WriteString("- 💰 **资金序列**:成交量序列、持仓量(OI)序列、资金费率\n")
|
||||
sb.WriteString("- 🎯 **筛选标记**:AI500评分 / OI_Top排名(如果有标注)\n\n")
|
||||
sb.WriteString("**你拥有的完整数据(多时间框架分析)**:\n\n")
|
||||
sb.WriteString("**📊 四个时间框架序列**(每个包含最近10个数据点):\n")
|
||||
sb.WriteString("1. **3分钟序列**:用于获取实时价格(当前价格 = 最后一根K线的收盘价)\n")
|
||||
sb.WriteString(" - Mid prices, EMA20, MACD, RSI7, RSI14\n")
|
||||
sb.WriteString("2. **15分钟序列**:短期趋势过滤(覆盖最近2.5小时)\n")
|
||||
sb.WriteString(" - Mid prices, EMA20, MACD, RSI7, RSI14\n")
|
||||
sb.WriteString("3. **1小时序列**:中期趋势确认(覆盖最近10小时)\n")
|
||||
sb.WriteString(" - Mid prices, EMA20, MACD, RSI7, RSI14\n")
|
||||
sb.WriteString("4. **4小时序列**:长期趋势方向(覆盖最近40小时)\n")
|
||||
sb.WriteString(" - EMA20 vs EMA50, ATR, Volume, MACD, RSI14\n\n")
|
||||
sb.WriteString("**💰 资金数据**:\n")
|
||||
sb.WriteString("- 持仓量(OI)变化、资金费率、成交量对比\n\n")
|
||||
sb.WriteString("**🎯 多时间框架分析建议**:\n")
|
||||
sb.WriteString("- **趋势共振**:当15m/1h/4h三个时间框架方向一致时 → 高信心度信号\n")
|
||||
sb.WriteString("- **趋势过滤**:用1h和4h确认主趋势,避免在震荡中交易\n")
|
||||
sb.WriteString("- **入场时机**:用15m寻找入场点,确保不在短期逆势位置开仓\n")
|
||||
sb.WriteString("- **背离识别**:价格创新高但MACD未创新高(多时间框架对比)\n")
|
||||
sb.WriteString("- **假突破过滤**:15m突破但1h/4h未确认 → 可能是假突破\n\n")
|
||||
sb.WriteString("**分析方法**(完全由你自主决定):\n")
|
||||
sb.WriteString("- 自由运用序列数据,你可以做但不限于趋势分析、形态识别、支撑阻力、技术阻力位、斐波那契、波动带计算\n")
|
||||
sb.WriteString("- 多维度交叉验证(价格+量+OI+指标+序列形态)\n")
|
||||
sb.WriteString("- 自由运用多时间框架序列,做趋势分析、形态识别、支撑阻力、背离判断\n")
|
||||
sb.WriteString("- 多维度交叉验证(多时间框架 + 量价 + OI + 资金费率)\n")
|
||||
sb.WriteString("- 用你认为最有效的方法发现高确定性机会\n")
|
||||
sb.WriteString("- 综合信心度 ≥ 75 才开仓\n\n")
|
||||
sb.WriteString("- **综合信心度 ≥ 75 才开仓**\n\n")
|
||||
sb.WriteString("**避免低质量信号**:\n")
|
||||
sb.WriteString("- 单一时间框架分析(必须多时间框架共振)\n")
|
||||
sb.WriteString("- 时间框架矛盾(15m上涨但1h/4h下跌)\n")
|
||||
sb.WriteString("- 单一维度(只看一个指标)\n")
|
||||
sb.WriteString("- 相互矛盾(涨但量萎缩)\n")
|
||||
sb.WriteString("- 横盘震荡\n")
|
||||
sb.WriteString("- 横盘震荡(多个时间框架都无明确趋势)\n")
|
||||
sb.WriteString("- 刚平仓不久(<15分钟)\n\n")
|
||||
|
||||
// === 夏普比率自我进化 ===
|
||||
|
||||
192
market/data.go
192
market/data.go
@@ -21,8 +21,10 @@ type Data struct {
|
||||
CurrentRSI7 float64
|
||||
OpenInterest *OIData
|
||||
FundingRate float64
|
||||
IntradaySeries *IntradayData
|
||||
LongerTermContext *LongerTermData
|
||||
IntradaySeries *IntradayData // 3分钟数据 - 实时价格
|
||||
MidTermSeries15m *MidTermData15m // 15分钟数据 - 短期趋势
|
||||
MidTermSeries1h *MidTermData1h // 1小时数据 - 中期趋势
|
||||
LongerTermContext *LongerTermData // 4小时数据 - 长期趋势
|
||||
}
|
||||
|
||||
// OIData Open Interest数据
|
||||
@@ -31,7 +33,7 @@ type OIData struct {
|
||||
Average float64
|
||||
}
|
||||
|
||||
// IntradayData 日内数据(3分钟间隔)
|
||||
// IntradayData 日内数据(3分钟间隔) - 主要用于获取实时价格
|
||||
type IntradayData struct {
|
||||
MidPrices []float64
|
||||
EMA20Values []float64
|
||||
@@ -40,6 +42,24 @@ type IntradayData struct {
|
||||
RSI14Values []float64
|
||||
}
|
||||
|
||||
// MidTermData15m 15分钟时间框架数据 - 短期趋势过滤
|
||||
type MidTermData15m struct {
|
||||
MidPrices []float64
|
||||
EMA20Values []float64
|
||||
MACDValues []float64
|
||||
RSI7Values []float64
|
||||
RSI14Values []float64
|
||||
}
|
||||
|
||||
// MidTermData1h 1小时时间框架数据 - 中期趋势确认
|
||||
type MidTermData1h struct {
|
||||
MidPrices []float64
|
||||
EMA20Values []float64
|
||||
MACDValues []float64
|
||||
RSI7Values []float64
|
||||
RSI14Values []float64
|
||||
}
|
||||
|
||||
// LongerTermData 长期数据(4小时时间框架)
|
||||
type LongerTermData struct {
|
||||
EMA20 float64
|
||||
@@ -68,13 +88,25 @@ func Get(symbol string) (*Data, error) {
|
||||
// 标准化symbol
|
||||
symbol = Normalize(symbol)
|
||||
|
||||
// 获取3分钟K线数据 (最近10个)
|
||||
// 获取3分钟K线数据 (最近10个) - 用于实时价格
|
||||
klines3m, err := getKlines(symbol, "3m", 40) // 多获取一些用于计算
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取3分钟K线失败: %v", err)
|
||||
}
|
||||
|
||||
// 获取4小时K线数据 (最近10个)
|
||||
// 获取15分钟K线数据 (最近10个) - 短期趋势
|
||||
klines15m, err := getKlines(symbol, "15m", 40)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取15分钟K线失败: %v", err)
|
||||
}
|
||||
|
||||
// 获取1小时K线数据 (最近10个) - 中期趋势
|
||||
klines1h, err := getKlines(symbol, "1h", 60)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取1小时K线失败: %v", err)
|
||||
}
|
||||
|
||||
// 获取4小时K线数据 (最近10个) - 长期趋势
|
||||
klines4h, err := getKlines(symbol, "4h", 60) // 多获取用于计算指标
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取4小时K线失败: %v", err)
|
||||
@@ -115,10 +147,16 @@ func Get(symbol string) (*Data, error) {
|
||||
// 获取Funding Rate
|
||||
fundingRate, _ := getFundingRate(symbol)
|
||||
|
||||
// 计算日内系列数据
|
||||
// 计算日内系列数据 (3分钟)
|
||||
intradayData := calculateIntradaySeries(klines3m)
|
||||
|
||||
// 计算长期数据
|
||||
// 计算15分钟系列数据
|
||||
midTermData15m := calculateMidTermSeries15m(klines15m)
|
||||
|
||||
// 计算1小时系列数据
|
||||
midTermData1h := calculateMidTermSeries1h(klines1h)
|
||||
|
||||
// 计算长期数据 (4小时)
|
||||
longerTermData := calculateLongerTermData(klines4h)
|
||||
|
||||
return &Data{
|
||||
@@ -132,6 +170,8 @@ func Get(symbol string) (*Data, error) {
|
||||
OpenInterest: oiData,
|
||||
FundingRate: fundingRate,
|
||||
IntradaySeries: intradayData,
|
||||
MidTermSeries15m: midTermData15m,
|
||||
MidTermSeries1h: midTermData1h,
|
||||
LongerTermContext: longerTermData,
|
||||
}, nil
|
||||
}
|
||||
@@ -340,6 +380,96 @@ func calculateIntradaySeries(klines []Kline) *IntradayData {
|
||||
return data
|
||||
}
|
||||
|
||||
// calculateMidTermSeries15m 计算15分钟系列数据
|
||||
func calculateMidTermSeries15m(klines []Kline) *MidTermData15m {
|
||||
data := &MidTermData15m{
|
||||
MidPrices: make([]float64, 0, 10),
|
||||
EMA20Values: make([]float64, 0, 10),
|
||||
MACDValues: make([]float64, 0, 10),
|
||||
RSI7Values: make([]float64, 0, 10),
|
||||
RSI14Values: make([]float64, 0, 10),
|
||||
}
|
||||
|
||||
// 获取最近10个数据点
|
||||
start := len(klines) - 10
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
for i := start; i < len(klines); i++ {
|
||||
data.MidPrices = append(data.MidPrices, klines[i].Close)
|
||||
|
||||
// 计算每个点的EMA20
|
||||
if i >= 19 {
|
||||
ema20 := calculateEMA(klines[:i+1], 20)
|
||||
data.EMA20Values = append(data.EMA20Values, ema20)
|
||||
}
|
||||
|
||||
// 计算每个点的MACD
|
||||
if i >= 25 {
|
||||
macd := calculateMACD(klines[:i+1])
|
||||
data.MACDValues = append(data.MACDValues, macd)
|
||||
}
|
||||
|
||||
// 计算每个点的RSI
|
||||
if i >= 7 {
|
||||
rsi7 := calculateRSI(klines[:i+1], 7)
|
||||
data.RSI7Values = append(data.RSI7Values, rsi7)
|
||||
}
|
||||
if i >= 14 {
|
||||
rsi14 := calculateRSI(klines[:i+1], 14)
|
||||
data.RSI14Values = append(data.RSI14Values, rsi14)
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// calculateMidTermSeries1h 计算1小时系列数据
|
||||
func calculateMidTermSeries1h(klines []Kline) *MidTermData1h {
|
||||
data := &MidTermData1h{
|
||||
MidPrices: make([]float64, 0, 10),
|
||||
EMA20Values: make([]float64, 0, 10),
|
||||
MACDValues: make([]float64, 0, 10),
|
||||
RSI7Values: make([]float64, 0, 10),
|
||||
RSI14Values: make([]float64, 0, 10),
|
||||
}
|
||||
|
||||
// 获取最近10个数据点
|
||||
start := len(klines) - 10
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
for i := start; i < len(klines); i++ {
|
||||
data.MidPrices = append(data.MidPrices, klines[i].Close)
|
||||
|
||||
// 计算每个点的EMA20
|
||||
if i >= 19 {
|
||||
ema20 := calculateEMA(klines[:i+1], 20)
|
||||
data.EMA20Values = append(data.EMA20Values, ema20)
|
||||
}
|
||||
|
||||
// 计算每个点的MACD
|
||||
if i >= 25 {
|
||||
macd := calculateMACD(klines[:i+1])
|
||||
data.MACDValues = append(data.MACDValues, macd)
|
||||
}
|
||||
|
||||
// 计算每个点的RSI
|
||||
if i >= 7 {
|
||||
rsi7 := calculateRSI(klines[:i+1], 7)
|
||||
data.RSI7Values = append(data.RSI7Values, rsi7)
|
||||
}
|
||||
if i >= 14 {
|
||||
rsi14 := calculateRSI(klines[:i+1], 14)
|
||||
data.RSI14Values = append(data.RSI14Values, rsi14)
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// calculateLongerTermData 计算长期数据
|
||||
func calculateLongerTermData(klines []Kline) *LongerTermData {
|
||||
data := &LongerTermData{
|
||||
@@ -493,6 +623,54 @@ func Format(data *Data) string {
|
||||
}
|
||||
}
|
||||
|
||||
if data.MidTermSeries15m != nil {
|
||||
sb.WriteString("Mid‑term series (15‑minute intervals, oldest → latest):\n\n")
|
||||
|
||||
if len(data.MidTermSeries15m.MidPrices) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("Mid prices: %s\n\n", formatFloatSlice(data.MidTermSeries15m.MidPrices)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries15m.EMA20Values) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("EMA indicators (20‑period): %s\n\n", formatFloatSlice(data.MidTermSeries15m.EMA20Values)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries15m.MACDValues) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("MACD indicators: %s\n\n", formatFloatSlice(data.MidTermSeries15m.MACDValues)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries15m.RSI7Values) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("RSI indicators (7‑Period): %s\n\n", formatFloatSlice(data.MidTermSeries15m.RSI7Values)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries15m.RSI14Values) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("RSI indicators (14‑Period): %s\n\n", formatFloatSlice(data.MidTermSeries15m.RSI14Values)))
|
||||
}
|
||||
}
|
||||
|
||||
if data.MidTermSeries1h != nil {
|
||||
sb.WriteString("Mid‑term series (1‑hour intervals, oldest → latest):\n\n")
|
||||
|
||||
if len(data.MidTermSeries1h.MidPrices) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("Mid prices: %s\n\n", formatFloatSlice(data.MidTermSeries1h.MidPrices)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries1h.EMA20Values) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("EMA indicators (20‑period): %s\n\n", formatFloatSlice(data.MidTermSeries1h.EMA20Values)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries1h.MACDValues) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("MACD indicators: %s\n\n", formatFloatSlice(data.MidTermSeries1h.MACDValues)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries1h.RSI7Values) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("RSI indicators (7‑Period): %s\n\n", formatFloatSlice(data.MidTermSeries1h.RSI7Values)))
|
||||
}
|
||||
|
||||
if len(data.MidTermSeries1h.RSI14Values) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("RSI indicators (14‑Period): %s\n\n", formatFloatSlice(data.MidTermSeries1h.RSI14Values)))
|
||||
}
|
||||
}
|
||||
|
||||
if data.LongerTermContext != nil {
|
||||
sb.WriteString("Longer‑term context (4‑hour timeframe):\n\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user