ema双均线趋势策略

This commit is contained in:
2025-10-26 01:52:05 +08:00
parent 04ad5b6f1b
commit 2e4b08ac8c
2 changed files with 286 additions and 0 deletions

81
trend.py Normal file
View File

@@ -0,0 +1,81 @@
import vectorbt as vbt
import pandas as pd
# ========================
# 数据加载
# ========================
# 从本地读取 ETH/USDT 1天K线数据来自OKX
df = pd.read_feather("/Users/aszer/Documents/vscode/cta/user_data/data/okx/ADA_USDT-1d.feather")
# 提取收盘价作为交易价格
price = df["close"]
# ========================
# 技术指标计算
# ========================
# 计算10日指数移动平均线EMA
ema_10 = vbt.MA.run(price, window=10, ewm=True).ma
# 计算20日指数移动平均线EMA
ema_20 = vbt.MA.run(price, window=20, ewm=True).ma
# 计算6周期相对强弱指数RSI
rsi_6 = vbt.RSI.run(price, window=6).rsi
# 计算12周期相对强弱指数RSI
rsi_12 = vbt.RSI.run(price, window=12).rsi
# ========================
# 买入条件定义
# ========================
# 条件1EMA多头排列 + 短期趋势加速
# - EMA10 > EMA20短期趋势强于长期趋势多头排列
# - EMA10昨日 > 前日:短期均线继续上行,显示动量增强
ema_bullish_cross = (ema_10 > ema_20) & (ema_10.shift(1) > ema_10.shift(2))
# 条件2双周期RSI进入深度超卖区暗示反弹可能
# - 过去3天含前天的6周期RSI最高值 < 21表示近期极度超卖
# - 过去3天的12周期RSI最高值 < 26.25,确认中周期也处于超卖状态
# 注:此条件未显式检查“今日反弹”,可后续增强
rsi_oversold_bounce = (rsi_6.shift(1).rolling(3).max() < 21) & \
(rsi_12.shift(1).rolling(3).max() < 26.25)
# 合并所有买入信号:任一条件满足即产生买入信号
entries = ema_bullish_cross | rsi_oversold_bounce
# ========================
# 卖出条件定义
# ========================
# 计算长期均线与短期均线的价差(空头趋势强度)
diff = ema_20 - ema_10 # 当diff扩大表示空头趋势加强
# 条件1EMA10连续5天下跌动量走弱
# - 当前EMA10 < 过去5天不含今日的最低EMA10值
ema10_falling = ema_10 < ema_10.shift(1).rolling(window=5).min()
# 条件2空头趋势加速价差达到近期最大
# - 当前diff是过去6天含今日中的最大值表示空头力量最强
diff_expanding = diff == diff.rolling(window=6).max()
# 合并卖出信号:两个条件同时满足才卖出
sell_cond = ema10_falling & diff_expanding
exits = sell_cond
# ========================
# 回测执行
# ========================
# 使用 vectorbt 的信号回测引擎,构建投资组合
pf = vbt.Portfolio.from_signals(
price, # 价格序列
entries, # 买入信号
exits, # 卖出信号
init_cash=100, # 初始资金 100 USDT
fees=0.001, # 交易手续费 0.1%(买卖均收)
sl_stop=0.05, # 止损从最高价回撤5%时触发
freq="1D" # 数据频率为每日,用于复利和年化计算
)
# ========================
# 输出回测统计结果
# ========================
print(pf.stats())