python量化交易策略——唐奇安通道和海龟策略(1)

本文采用唐奇安通道和海龟策略相结合的方式

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
import numpy as np
import pandas as pd
from gm.api import *

'''
本策略基于海龟交易法的唐奇安通道。
以价格突破唐奇安通道的上下轨作为开仓信号,N倍ATR作为加仓或止损点。
'''


def init(context):
    # 设置合约标的
    context.symbol = 'DCE.I'
    # 设置计算唐奇安通道的参数
    context.n = 20
    # 设置ATR倍数
    context.atr_multiple = 0.5
    # 设置单笔开仓数量
    context.order_volume = 2
    # 设置单笔加减仓数量
    context.change_volume = 2
    # 订阅数据
    subscribe(symbols=context.symbol, frequency='60s', count=2)
    # 定时函数,开盘时运行
    schedule(schedule_func=algo, date_rule='1d', time_rule='09:00:00')
    schedule(schedule_func=algo, date_rule='1d', time_rule='21:00:00')


def algo(context):
    # 上一交易日
    last_date = get_previous_trading_date(exchange='SHFE', date=context.now)
    # 调取数据
    data = history_n(symbol=context.symbol, frequency='1d', count=context.n + 1, end_time=last_date,
                     fields='close,high,low,bob', df=True)  # 计算ATR
    # 计算ATR
    tr_list = []
    for i in range(1, len(data) - 1):
        tr = max(max((data['high'].iloc[i] - data['low'].iloc[i]),
                     abs(data['close'].shift(1).iloc[i] - data['high'].iloc[i])),
                 abs(data['close'].shift(1).iloc[i] - data['low'].iloc[i]))
        tr_list.append(tr)
    context.atr = int(np.floor(np.mean(tr_list)))
    context.atr_half = int(np.floor(context.atr_multiple * context.atr))
    # 计算唐奇安通道
    context.don_upper = np.max(data['high'].values[-context.n - 1:-1])
    context.don_lower = np.min(data['low'].values[-context.n - 1:-1])
    # 计算加仓点和止损点
    context.long_add_point = context.don_upper + context.atr_half  # 多仓加仓点
    context.long_stop_loss = context.don_upper - context.atr_half  # 多仓止损点
    context.short_add_point = context.don_lower - context.atr_half  # 空仓加仓点
    context.short_stop_loss = context.don_lower + context.atr_half  # 空仓止损点


def on_bar(context, bars):
    # 提取数据
    symbol = bars[0]['symbol']
    recent_data = context.data(symbol=context.symbol, frequency='60s', count=2, fields='close,high,low')
    new_price = recent_data['close'].values[-1]

    # 账户仓位情况
    position_long = context.account().position(symbol=symbol, side=PositionSide_Long)
    position_short = context.account().position(symbol=symbol, side=PositionSide_Short)

    # 当无持仓时
    if not position_long and not position_short:
        # 如果向上突破唐奇安通道上轨,则开多
        if new_price > context.don_upper:
            order_volume(symbol=symbol, side=OrderSide_Buy, volume=context.order_volume, order_type=OrderType_Market,
                         position_effect=PositionEffect_Open)
        # 如果向下突破唐奇安通道下轨,则开空
        if new_price < context.don_lower:
            order_volume(symbol=symbol, side=OrderSide_Sell, volume=context.order_volume, order_type=OrderType_Market,
                         position_effect=PositionEffect_Open)

    # 有持仓时
    # 持多仓
    if position_long:
        # 当突破加仓点时:加仓
        if new_price > context.long_add_point:
            order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Buy, order_type=OrderType_Market,
                         position_effect=PositionEffect_Open)
            context.long_add_point += context.atr_half
            context.long_stop_loss += context.atr_half
        # 当跌破止损点时:减仓或清仓
        if new_price < context.long_stop_loss:
            volume_hold = position_long['volume']
            if volume_hold > context.order_volume:
                order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Sell,
                             order_type=OrderType_Market, position_effect=PositionEffect_Close)
            else:
                order_volume(symbol=symbol, volume=volume_hold, side=OrderSide_Sell, order_type=OrderType_Market,
                             position_effect=PositionEffect_Close)
            context.long_add_point -= context.atr_half
            context.long_stop_loss -= context.atr_half

    # 持空仓
    if position_short:
        # 当跌破加仓点时:加仓
        if new_price < context.short_add_point:
            order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Sell, order_type=OrderType_Market,
                         position_effect=PositionEffect_Open)
            context.short_add_point -= context.atr_half
            context.short_stop_loss -= context.atr_half
        # 当突破止损点时:减仓或清仓
        if new_price > context.short_stop_loss:
            volume_hold = position_short['volume']
            if volume_hold > context.atr_half:
                order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Buy,
                             order_type=OrderType_Market, position_effect=PositionEffect_Close)
            else:
                order_volume(symbol=symbol, volume=volume_hold, side=OrderSide_Buy, order_type=OrderType_Market,
                             position_effect=PositionEffect_Close)
            context.short_add_point += context.atr_half
            context.short_stop_loss += context.atr_half


def on_order_status(context, order):
    # 标的代码
    symbol = order['symbol']
    # 委托价格
    price = order['price']
    # 委托数量
    volume = order['volume']
    # 目标仓位
    target_percent = order['target_percent']
    # 查看下单后的委托状态,等于3代表委托全部成交
    status = order['status']
    # 买卖方向,1为买入,2为卖出
    side = order['side']
    # 开平仓类型,1为开仓,2为平仓
    effect = order['position_effect']
    # 委托类型,1为限价委托,2为市价委托
    order_type = order['order_type']
    if status == 3:
        if effect == 1 and side == 1:
            side_effect = '开多仓'
        elif effect == 1 and side == 2:
            side_effect = '开空仓'
        elif effect == 2 and side == 1:
            side_effect = '平空仓'
        elif effect == 2 and side == 2:
            side_effect = '平多仓'
        order_type_word = '限价' if order_type == 1 else '市价'
        print('{}:标的:{},操作:以{}{},委托价格:{},委托数量:{}'.format(context.now, symbol, order_type_word, side_effect, price,
                                                         volume))


def on_backtest_finished(context, indicator):
    print('*' * 50)
    print('回测已完成,请通过右上角“回测历史”功能查询详情。')


if __name__ == '__main__':
    '''
    strategy_id策略ID,由系统生成
    filename文件名,请与本文件名保持一致
    mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    token绑定计算机的ID,可在系统设置-密钥管理中生成
    backtest_start_time回测开始时间
    backtest_end_time回测结束时间
    backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    backtest_initial_cash回测初始资金
    backtest_commission_ratio回测佣金比例
    backtest_slippage_ratio回测滑点比例
    '''
    run(strategy_id='99ff6300-f074-11ec-9359-a4c3f0c417b1',
        filename='main.py',
        mode=MODE_BACKTEST,
        #这里填写你的token编码,这里不方便填写
        token='**************************',
        backtest_start_time='2020-03-01 09:00:00',
        backtest_end_time='2020-06-30 15:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=1000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
唐奇安通道和布林带通道都是常用的技术分析指标,用于判断股票价格的趋势和波动情况。下面是对唐奇安通道和布林带通道的介绍和Python代码实现: 1. 唐奇安通道 唐奇安通道是由三条轨道线构成的,分别是通道上界、通道下界和中轨道。其中,通道上界等于过去20日内的最高价,通道下界等于过去20日内的最低价,中轨道等于通道上界和通道下界的平均值。唐奇安通道的突破是指股票价格突破了通道上界或通道下界,这通常被视为一个买入或卖出信号。 2. 布林带通道 布林带通道也是由三条轨道线构成的,分别是通道上界、通道下界和中轨道。其中,通道上界等于中轨道加上两倍的标准差,通道下界等于中轨道减去两倍的标准差,中轨道等于股票价格的移动平均线。布林带通道的突破是指股票价格突破了通道上界或通道下界,这通常被视为一个买入或卖出信号。 下面是Python代码实现唐奇安通道和布林带通道: ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt # 计算唐奇安通道 def donchian_channel(high, low, window=20): channel_up = high.rolling(window=window).max() channel_down = low.rolling(window=window).min() channel_mid = (channel_up + channel_down) / 2 return channel_up, channel_down, channel_mid # 计算布林带通道 def bollinger_band(close, window=20, k=2): std = close.rolling(window=window).std() band_up = close.rolling(window=window).mean() + k * std band_down = close.rolling(window=window).mean() - k * std band_mid = close.rolling(window=window).mean() return band_up, band_down, band_mid # 读取股票数据 df = pd.read_csv('stock.csv', index_col='date', parse_dates=True) # 计算唐奇安通道和布林带通道 channel_up, channel_down, channel_mid = donchian_channel(df['high'], df['low']) band_up, band_down, band_mid = bollinger_band(df['close']) # 绘制K线图和唐奇安通道、布林带通道 fig, ax = plt.subplots(figsize=(16, 8)) ax.set_title('Stock Price') ax.set_ylabel('Price') ax.grid(True) candlestick_ohlc(ax, zip(mdates.date2num(df.index.to_pydatetime()), df['open'], df['high'], df['low'], df['close']), width=0.6, colorup='red', colordown='green') ax.plot(df.index, channel_up, label='Donchian Channel Up', color='blue') ax.plot(df.index, channel_down, label='Donchian Channel Down', color='blue') ax.plot(df.index, band_up, label='Bollinger Band Up', color='orange') ax.plot(df.index, band_down, label='Bollinger Band Down', color='orange') ax.legend(loc='upper left') plt.show() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

做量化的智明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值