龙听期货论坛's Archiver

龙听 发表于 2018-3-24 17:33

Hans123日内策略[Python源码]

1.策略介绍

作为外汇市场上广为流行的一种突破交易策略,HANS123以其简洁的开盘后N根K线的高低点突破,作为交易信号触发的评判标准。这也是一种入场较早的交易模式,配合适当过滤技术,或可提高其胜算。
过滤原理:这个过滤是为了让市场消化品种隔夜的各种信息,当有些突发信息公布,市场分歧很大的时候,开盘会呈现方向不明、宽幅震荡的情况,此时,对任何突破策略都会是灾难,所以忽略这段时间。

策略原理:

日内交易策略,收盘平仓;
HANS123在开盘30分钟后准备入场;
上轨=开盘后30分钟高点;
下轨=开盘后30分钟低点;
当价格突破上轨,买入开仓;
当价格跌穿下轨,卖出开仓。

2.策略代码

2.1配置文件【HANS123.ini】(提示ini配置文件,需要保存成UTF8格式)

[code]
[strategy]
td_addr=localhost:8001
username=
password=
strategy_id=
mode=4
;订阅代码注意及时更新
subscribe_symbols=CFFEX.IF1707.tick,CFFEX.IF1707.bar.60

[backtest]
start_time=2017-6-01 09:00:00
end_time=2017-7-16 15:15:00
initial_cash=10000000
transaction_ratio=1
commission_ratio=0
slippage_ratio=0

[para]
trade_symbol=CFFEX.IF1707
open_time=09:15:00
hans_time=09:45:00
ex_time=15:10:00
limit_times=3
[/code]


2.2策略文件【HANS123.py】

[code]
# encoding: utf-8
from gmsdk.api import StrategyBase
from gmsdk import md
from gmsdk.enums import *
import arrow
import time

# 每次开仓量
OPEN_VOL = 5

# 最大开仓次数
MAX_TRADING_TIMES = 50


class Hans123(StrategyBase):
    def __init__(self, *args, **kwargs):
        super(Hans123, self).__init__(*args, **kwargs)

        # 是否已获取当天时间标识
        self.time_flag = False

        # 是否已获取当天上、下轨数据
        self.data_flag = False

        # 持仓量
        self.long_holding = 0;
        self.short_holding = 0;

        # 当天交易次数
        self.trading_times = 0;

        self.__get_param()

    def __get_param(self):
        '''
        获取配置参数
        '''
        # 交易证券代码
        self.trade_symbol = self.config.get('para', 'trade_symbol')
        pos = self.trade_symbol.find('.')
        self.exchange = self.trade_symbol[:pos]
        self.sec_id = self.trade_symbol[pos + 1:]

        # 开盘时间
        self.open_time = self.config.get('para', 'open_time')

        # hans时间
        self.hans_time = self.config.get('para', 'hans_time')

        # 强制平仓时间
        self.ex_time = self.config.get('para', 'ex_time')

    def __get_time(self, cur_utc):
        '''
        获取当天的重要时间参数
        '''
        utc = arrow.get(cur_utc).replace(tzinfo='local')
        cur_date = utc.format('YYYY-MM-DD')
        FMT = '%s %s'
        self.today_open_time = FMT % (cur_date, self.open_time)
        print('today open time: %s' % self.today_open_time)

        self.today_hans_time = FMT % (cur_date, self.hans_time)
        print('today hans time: %s' % self.today_hans_time)

        today_ex_time = FMT % (cur_date, self.ex_time)
        print('today exit time:%s' % today_ex_time)

        self.ex_time_utc = arrow.get(today_ex_time).replace(tzinfo='local').timestamp
        self.hans_time_utc = arrow.get(self.today_hans_time).replace(tzinfo='local').timestamp

    def __init_band_data(self, bar_type):
        '''
        获取上、下轨数据
        '''
        bars = self.get_bars(self.trade_symbol, bar_type, self.today_open_time, self.today_hans_time)
        close_list = [bar.close for bar in bars]

        # 上轨
        self.upr_band = max(close_list)
        print('upper band:%s' % self.upr_band)

        # 下轨
        self.dwn_band = min(close_list)
        print('down band: %s' % self.dwn_band)

    def on_tick(self, tick):
        '''
        tick行情事件
        '''
        # 获取最新价
        self.last_price = tick.last_price

    def on_bar(self, bar):
        '''
        bar周期数据事件
        '''
        # 获取当天的时间参数
        if self.time_flag is False:
            self.__get_time(bar.utc_time)
            self.time_flag = True

        # 计算上、下轨
        if bar.utc_time < self.ex_time_utc and bar.utc_time > self.hans_time_utc:
            if self.time_flag is True and self.data_flag is False:
                self.__init_band_data(bar.bar_type)
                self.data_flag = True

        # 休市前强平当天仓位
        if bar.utc_time > self.ex_time_utc:
            if self.long_holding > 0:
                self.close_long(self.exchange, self.sec_id, 0, self.long_holding)
                print('exit time close long: %s, vol: %s' % (self.trade_symbol, self.long_holding))
                self.long_holding = 0

            elif self.short_holding > 0:
                self.close_short(self.exchange, self.sec_id, 0, self.short_holding)
                print('exit time close long: %s, vol: %s' % (self.trade_symbol, self.short_holding))
                self.short_holding = 0
            return

        if self.trading_times > MAX_TRADING_TIMES:
            print('trading times more than max trading times, stop trading')
            return

        # 交易时间段
        if bar.utc_time > self.hans_time_utc and bar.utc_time < self.ex_time_utc:
            if bar.close > self.upr_band:
                if self.short_holding > 0:
                    # 有空仓,先平空仓
                    self.close_short(self.exchange, self.sec_id, 0, self.short_holding)
                    print('close short: %s, vol:%s' % (self.trade_symbol, self.short_holding))
                    self.short_holding = 0

                # 开多仓
                self.open_long(self.exchange, self.sec_id, 0, OPEN_VOL)
                print('open long: %s, vol:%s' % (self.trade_symbol, OPEN_VOL))
                self.long_holding += OPEN_VOL

                # 开仓次数+1
                self.trading_times += 1
            elif bar.close < self.dwn_band:
                if self.long_holding > 0:
                    # 有多仓,先平多仓
                    self.close_long(self.exchange, self.sec_id, 0, self.long_holding)
                    print('close long: %s, vol:%s' % (self.trade_symbol, self.long_holding))
                    self.long_holding = 0

                # 开空仓
                self.open_short(self.exchange, self.sec_id, 0, OPEN_VOL)
                print('open short: %s, vol:%s' % (self.trade_symbol, OPEN_VOL))
                self.short_holding += OPEN_VOL

                # 开仓次数+1
                self.trading_times += 1

if __name__ == '__main__':
    hans123 = Hans123(config_file='Hans123.ini')
    ret = hans123.run()
print(hans123.get_strerror(ret))
[/code]


3.回测结果

[img]http://p.qhlt.cn/filestores/2018/03/24/e44ff3783db35c4ba9011969e54e7924.png[/img]


[font=SimSun, STSong][size=15px][size=16px]4.代码涉及的函数[/size][/size][/font][font=SimSun, STSong][size=15px][size=3]   [/size][/size][/font]
[font=SimSun, STSong][size=15px][size=3]   4.1Python相关函数
[/size][/size][/font][table=98%]
[tr][td=1,2][/td][td=1,2]功能[/td][td=1,2]函数原型[/td][td=2,1]参数[/td][td=1,2]返回值[/td][/tr]
[tr][td]参数名[/td][td]含义[/td][/tr]
[tr][td]sys[/td][td=5,1]提供了一系列有关Python运行环境的变量和函数。[/td][/tr]
[tr][td][/td][td][/td][td][/td][td]sys.argv[0][/td][td]当前程序名[/td][td][/td][/tr]
[tr][td=1,2]sys.argv[/td][td=1,2]获取当前正在执行的命令行参数的参数列表(list)。[/td][td=1,2]sys.argv[/td][td]sys.argv[1][/td][td]第一个参数[/td][td][/td][/tr]
[tr][td]sys.argv[2][/td][td]第二个参数[/td][td][/td][/tr]
[tr][td]arrow[/td][td=5,1]标准的时间日期库。[/td][/tr]
[tr][td]time[/td][td]返回当前时间的时间戳[/td][td]time.time()[/td][td][/td][td][/td][td]返回当前时间的时间戳[/td][/tr]
[tr][td]len[/td][td]返回对象(字符、列表、元组等)长度或项目个数。[/td][td]len(s)[/td][td]s[/td][td]对象[/td][td]返回对象长度。[/td][/tr]
[tr][td]append[/td][td]用于在列表末尾添加新的对象。[/td][td]list.append(obj)[/td][td]obj[/td][td]添加到列表末尾的对象。[/td][td]该方法无返回值,但是会修改原来的列表。[/td][/tr]
[/table][font=SimSun, STSong][size=15px][size=4]  [/size][size=3] 4.2掘金接口函数[/size][/size][/font]
[table=98%]
[tr][td=1,2][/td][td=1,2]功能[/td][td=1,2]函数原型[/td][td=3,1]参数[/td][td=1,2]返回值[/td][/tr]
[tr][td]参数名[/td][td]类型[/td][td]说明[/td][/tr]
[tr][td]on_bar[/td][td]响应Bar事件,收到Bar数据后本函数被调用。[/td][td]on_bar(bar)[/td][td]bar[/td][td]bar[/td][td]bar数据[/td][td]无[/td][/tr]
[tr][td=1,4]open_long[/td][td=1,4]异步开多仓,以参数指定的symbol、价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口[/td][td=1,4]open_long(exchange, sec_id, price, volume)[/td][td]exchange[/td][td]string[/td][td]交易所代码, 如上交所SHSE[/td][td=1,4]委托下单生成的Order对象[/td][/tr]
[tr][td]sec_id[/td][td]string[/td][td]证券代码,如浦发银行600000[/td][/tr]
[tr][td]price[/td][td]float[/td][td]委托价,如果price=0,为市价单,否则为限价单[/td][/tr]
[tr][td]volume[/td][td]float[/td][td]委托量[/td][/tr]
[tr][td=1,4]close_long[/td][td=1,4]异步平多仓接口,以参数指定的exchange, 证券代码sec_id, 价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口。[/td][td=1,4]close_long(exchange, sec_id, price, volume)[/td][td]exchange[/td][td]string[/td][td]交易所代码, 如上交所SHSE[/td][td=1,4]委托下单生成的Order对象[/td][/tr]
[tr][td]sec_id[/td][td]string[/td][td]证券代码,如浦发银行600000[/td][/tr]
[tr][td]price[/td][td]float[/td][td]委托价,如果price=0,为市价单,否则为限价单[/td][/tr]
[tr][td]volume[/td][td]float[/td][td]平仓量[/td][/tr]
[tr][td=1,4]open_short[/td][td=1,4]异步开空仓,以参数指定的symbol、价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口[/td][td=1,4]open_short(exchange, sec_id, price, volume)[/td][td]exchange[/td][td]string[/td][td]交易所代码, 如上交所SHSE[/td][td=1,4]委托下单生成的Order对象[/td][/tr]
[tr][td]sec_id[/td][td]string[/td][td]证券代码,如浦发银行600000[/td][/tr]
[tr][td]price[/td][td]float[/td][td]委托价,如果price=0,为市价单,否则为限价单[/td][/tr]
[tr][td]volume[/td][td]float[/td][td]委托量[/td][/tr]
[tr][td=1,4]close_short[/td][td=1,4]异步平空仓接口,以参数指定的exchange, 证券代码sec_id, 价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口。[/td][td=1,4]close_long(exchange, sec_id, price, volume)[/td][td]exchange[/td][td]string[/td][td]交易所代码, 如上交所SHSE[/td][td=1,4]委托下单生成的Order对象[/td][/tr]
[tr][td]sec_id[/td][td]string[/td][td]证券代码,如浦发银行600000[/td][/tr]
[tr][td]price[/td][td]float[/td][td]委托价,如果price=0,为市价单,否则为限价单[/td][/tr]
[tr][td]volume[/td][td]float[/td][td]平仓量

[/td][/tr]
[/table]

碧云浩淼 发表于 2022-7-24 17:07

请教下版主:这个Hans123日内策略[Python源码]怎么改成MC代码???

页: [1]