3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于 斐波那契回调(Fibonacci Retracement) 的交易策略。
ContextInfo.paint() 函数在主图上实时画出这些关键支撑/压力线,方便可视化观察。# -*- coding: gbk -*-
import pandas as pd
import numpy as np
def init(ContextInfo):
# --- 策略参数设置 ---
ContextInfo.lookback = 100 # 回溯周期,用于寻找高低点
ContextInfo.account_id = '6000000000' # 请替换为您的资金账号
ContextInfo.account_type = 'STOCK' # 账号类型:'STOCK'股票, 'FUTURE'期货
# 斐波那契数列比例
ContextInfo.fib_ratios = [0.0, 0.236, 0.382, 0.5, 0.618, 0.786, 1.0]
# 设置股票池(示例)
ContextInfo.set_universe(['600000.SH'])
# 绑定账号(实盘必须)
ContextInfo.set_account(ContextInfo.account_id)
def handlebar(ContextInfo):
# 获取当前K线位置
index = ContextInfo.barpos
# 确保有足够的数据进行回溯计算
if index < ContextInfo.lookback:
return
# 获取当前主图品种代码
stock_code = ContextInfo.stockcode + '.' + ContextInfo.market
# 获取历史行情数据 (High, Low, Close)
# 注意:count=ContextInfo.lookback + 1 确保取到当前K线
data = ContextInfo.get_market_data_ex(
['high', 'low', 'close'],
[stock_code],
period=ContextInfo.period,
count=ContextInfo.lookback,
dividend_type='follow'
)
if stock_code not in data:
return
df = data[stock_code]
if df.empty:
return
# 计算窗口内的最高价和最低价及其位置
# argmax/argmin 返回的是相对位置,需要结合索引判断先后
high_prices = df['high'].values
low_prices = df['low'].values
close_prices = df['close'].values
max_price = np.max(high_prices)
min_price = np.min(low_prices)
max_idx = np.argmax(high_prices) # 最高价在窗口内的索引
min_idx = np.argmin(low_prices) # 最低价在窗口内的索引
current_price = close_prices[-1]
# --- 斐波那契计算逻辑 ---
# 定义趋势方向:
# 如果 最高价索引 > 最低价索引,说明是先低后高,为上升趋势(寻找回调支撑)
# 如果 最高价索引 < 最低价索引,说明是先高后低,为下降趋势(寻找反弹压力)
is_uptrend = max_idx > min_idx
price_range = max_price - min_price
fib_levels = {}
if is_uptrend:
# 上升趋势:0 是最高点,1 是最低点,回调是向下走
# Level = Max - Range * Ratio
for ratio in ContextInfo.fib_ratios:
level_price = max_price - (price_range * ratio)
fib_levels[ratio] = level_price
# 绘图:在主图绘制线条
# 0.618 和 0.5 重点显示为黄色和洋红色,其他为白色
color = 'white'
if ratio == 0.618: color = 'yellow'
if ratio == 0.5: color = 'magenta'
# paint(指标名, 数值, 位置(-1为主图), 线型(0为曲线), 颜色)
ContextInfo.paint(f'Fib_{ratio}', level_price, -1, 0, color)
else:
# 下降趋势:0 是最低点,1 是最高点,反弹是向上走
# Level = Min + Range * Ratio
for ratio in ContextInfo.fib_ratios:
level_price = min_price + (price_range * ratio)
fib_levels[ratio] = level_price
color = 'white'
if ratio == 0.618: color = 'yellow'
if ratio == 0.5: color = 'magenta'
ContextInfo.paint(f'Fib_{ratio}', level_price, -1, 0, color)
# --- 简单的交易逻辑示例 (仅针对上升趋势的回调做多) ---
# 实际交易请务必增加风控和仓位管理
if not ContextInfo.is_last_bar():
# 回测或历史K线只计算不交易,或者使用 passorder 的 quickTrade=0
# 这里为了演示逻辑,仅在最后一根K线判断
pass
# 获取当前持仓
positions = ContextInfo.get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
long_pos = 0
for pos in positions:
if pos.m_strInstrumentID == ContextInfo.stockcode:
long_pos = pos.m_nVolume
# 交易信号:上升趋势中,价格回调触及 0.618 支撑位
if is_uptrend:
buy_level = fib_levels[0.618]
stop_loss = fib_levels[0.786]
take_profit = fib_levels[0.236]
# 信号:当前价格跌破 0.618 但仍在 0.786 之上 (视为回调到位)
# 且当前没有持仓
if long_pos == 0 and current_price <= buy_level * 1.005 and current_price >= stop_loss:
print(f"触发买入信号: 价格 {current_price} 接近 Fib 0.618 {buy_level}")
# 全仓买入示例 (请根据实际情况调整 volume)
passorder(23, 1101, ContextInfo.account_id, stock_code, 5, -1, 100, ContextInfo)
# 止损/止盈逻辑
elif long_pos > 0:
if current_price < stop_loss:
print(f"触发止损: 价格 {current_price} 跌破 Fib 0.786 {stop_loss}")
passorder(24, 1101, ContextInfo.account_id, stock_code, 5, -1, long_pos, ContextInfo)
elif current_price > take_profit:
print(f"触发止盈: 价格 {current_price} 超过 Fib 0.236 {take_profit}")
passorder(24, 1101, ContextInfo.account_id, stock_code, 5, -1, long_pos, ContextInfo)
ContextInfo.paint:
f'Fib_{ratio}':给每条线起一个唯一的名字(如 Fib_0.618),这样在图表指标栏可以看到数值。-1:表示画在主图上(和 K 线叠加)。color:我将 0.618 设为黄色,0.5 设为洋红色,以便视觉上突出重点支撑位。滚动窗口 (lookback):
ContextInfo.lookback = 100,意味着它会动态计算过去 100 根 K 线内的最高和最低点。趋势判断 (is_uptrend):
max_idx) 和最低价索引 (min_idx) 的大小来判断当前是处于上升波段后的回调,还是下降波段后的反弹。交易执行 (passorder):
buy_level * 1.005 范围内)且未跌破 0.786 时买入。ContextInfo.account_id 为你的实际资金账号。Q: 为什么画出来的线是变动的?
A: 因为代码使用的是滚动窗口(过去100根K线)。当新的K线产生,旧的K线移出窗口,或者产生了新的最高/最低点时,计算基准就会改变。如果你需要固定某个日期的最高低点,需要修改代码指定固定的 start_time 和 end_time 来获取数据。
Q: 如何只画线不交易?
A: 你可以注释掉 passorder 相关的代码块,或者直接删除 if long_pos == 0 ... 之后的交易逻辑部分,这样策略就变成了一个纯粹的技术分析指标工具。
Q: get_market_data_ex 获取不到数据怎么办?
A: 请确保在 QMT 的“数据管理”中下载了对应品种和周期的历史数据。如果没有下载数据,API 返回的 DataFrame 可能是空的。