• 2
  • 1
  • 1
  • 5
  • 1







  • H

    简单又神奇的策略,就是这么简单,可是又很难弄,如果只是手动操作 估计会累死,,

    阅读更多
  • 什么是做市策略

    做市策略(market-maker strategy)是一种风险中立(risk-neutral)盘口价差套利策略。其基本原理是:在盘口的卖一和买一价之间,插入委买单和委卖单,如果插入的两个单子都成交的话,做市商就吃到了买卖单之间的价差,而整个过程结束后,做市商所持有的头寸并没有变化。如果买卖单之间的价差扣除各种交易手续费之后还有盈余,那么该做市商就获得了相应的盈利。

    做市策略是一种增加交易所流动性的策略,一般来讲,成熟的交易市场为了提升自身的流动性,会用低佣金(甚至为做市商提供流动性奖励金)的办法,吸引做市商来该市场做市。

    做市策略需要注意的事项

    1 做市时机的选择

    做市商本质上是整个市场的交易对手方。如果市场呈现急剧的单边行情,做市商下达的买卖委托单会大概率出现单边成交的情况,因此做市商手中就会积累大量的风险头寸,这是做市商不想承担的风险。因此,做市商在选择是否下达做市指令之前,都会预判一下市场的趋势明显程度,如果市场短期内呈现非常明显的趋势信号,做市商就会相应地减少自己的做市单数量(甚至停止做市)

    2 净头寸的处理

    做市商手中累计的净头寸,可以通过很多种办法来处理,下面列举其中两种:

    (1)在下一次做市时,处理掉累积的净头寸。比如做市商目前净头寸有2BTC,下次做市时,他就可以下达一个卖3BTC的委卖单,一个买1BTC的委买单。这种做法好处是净头寸可以及时得到处理,坏处是净头寸处理的时机(价格)可能不是最优的。

    (2)第二种方法是开立另外一个独立的程序,对累积的净头寸进行成本计算,然后按照成本价*(1+一定比例的手续费+一定比例的profit margin),将该头寸反向甩出市场,甩出方法又有两种:a. 按限价单从价优到价劣依次甩出市场,超时不成交的部分则撤单,等待下次机会;b. 先按限价单从价优到价劣依次甩出市场,超时不成交的部分,则按市价单甩货。第一种方法的好处是甩货成本可控,但是甩货周期可能会拖得比较长;第二种方法则能有效地控制甩货周期,但是成本不可控,孰优孰劣,需要做市商根据自己的风险偏好慎重考虑。

    3 期货换合约(移仓)的处理

    期货合约都有一个到期日,在到期日结束时刻的前几个小时,我们不建议做市商继续做市,而是利用这几个小时,将即将到期的期货合约进行移仓。移仓的意思就是平掉当前期货合约的仓位,然后再开同样仓位大小的下周合约。当然,移仓也是需要考虑成本的。如果当前持仓是多头,那么我们希望移仓的时间点是在下周期货贴水最厉害的时候;反之,我们则希望移仓的时间点是在下周期货升水最厉害的时候。等移仓做完以后,做市策略继续恢复执行。

    # coding=utf-8 from __future__ import print_function, absolute_import, unicode_literals from gm.api import * ''' 本策略通过不断对CZCE.CF801进行: 买(卖)一价现价单开多(空)仓和卖(买)一价平多(空)仓来做市 并以此赚取差价 回测数据为:CZCE.CF801的tick数据 回测时间为:2017-09-29 11:25:00到2017-09-29 11:30:00 需要特别注意的是:本平台对于回测对限价单固定完全成交,本例子 仅供参考. 敬请通过适当调整回测参数 1.backtest_commission_ratio回测佣金比例 2.backtest_slippage_ratio回测滑点比例 3.backtest_transaction_ratio回测成交比例 以及优化策略逻辑来达到更贴近实际的回测效果 ''' def init(context): # 订阅CZCE.CF801的tick数据 context.symbol = 'CZCE.CF801' subscribe(symbols=context.symbol, frequency='tick') def on_tick(context, tick): quotes = tick['quotes'][0] # 获取持有的多仓 positio_long = context.account().position(symbol=context.symbol, side=PositionSide_Long) # 获取持有的空仓 position_short = context.account().position(symbol=context.symbol, side=PositionSide_Short) print(quotes['bid_p']) print(quotes['ask_p']) # 没有仓位则双向开限价单 # 若有仓位则限价单平仓 if not positio_long: # 获取买一价 price = quotes['bid_p'] print('买一价为: ', price) order_target_volume(symbol=context.symbol, volume=1, price=price, order_type=OrderType_Limit, position_side=PositionSide_Long) print('CZCE.CF801开限价单多仓1手') else: # 获取卖一价 price = quotes['ask_p'] print('卖一价为: ', price) order_target_volume(symbol=context.symbol, volume=0, price=price, order_type=OrderType_Limit, position_side=PositionSide_Long) print('CZCE.CF801平限价单多仓1手') if not position_short: # 获取卖一价 price = quotes['ask_p'] print('卖一价为: ', price) order_target_volume(symbol=context.symbol, volume=1, price=price, order_type=OrderType_Limit, position_side=PositionSide_Short) print('CZCE.CF801卖一价开限价单空仓') else: # 获取买一价 price = quotes['bid_p'] print('买一价为: ', price) order_target_volume(symbol=context.symbol, volume=0, price=price, order_type=OrderType_Limit, position_side=PositionSide_Short) print('CZCE.CF801买一价平限价单空仓') 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回测滑点比例 backtest_transaction_ratio回测成交比例 ''' run(strategy_id='strategy_id', filename='main.py', mode=MODE_BACKTEST, token='token_id', backtest_start_time='2017-09-29 11:25:00', backtest_end_time='2017-09-29 11:30:00', backtest_adjust=ADJUST_PREV, backtest_initial_cash=500000, backtest_commission_ratio=0.00006, backtest_slippage_ratio=0.0001, backtest_transaction_ratio=0.5)

    阅读更多
  • 导语: 策略为基本模型,如使用请自行调整策略参数和接口。

    天然的海龟是一个比较成熟而完整的交易系统。构建交易系统的目的就是避免交易员自己做出主观的决策。这样才能真正的让概率发挥作用。海龟的主要捕捉的是趋势。其采用突破法来确定趋势,当价格突破时认为有买入的信号,而随着价格离当初突破的价格越来越远,我们认为趋势成立的概率就越来越高,加仓!那么,这个突破怎么确定呢?我们需要用到唐奇安通道的方法进行处理。
    唐奇安通道
    在海龟的系统的止盈止损中,实际上就是借助了唐奇安通道。那么,这唐奇安通道究竟是个什么东西呢?

    首先引入上线中线下线的概念。上线=Max(前N个交易日的最高价),下线=Min(前N个交易日的最低价),中线=(上线+下线)/2,每个交易日结束之后更新当天的数据。这里N一般默认取20。那么唐奇安通道就是这个上线和下线所形成的走势区间。所谓的突破,也就是指今日盘中股价高过了上线。参见下图:
    0_1530547564093_6.png

    这里有个小插曲,为什么默认的N是20呢?这有个典故——神奇数字。Donchian在开发唐奇安通道的期间,碰巧阅读到整形外科医生Maxwel Maltz博士在1960年所作的“心理控制论”(这本书在1989年被重新发现)。Maltz博士称在整形外科手术过程中,患者最少需要21日来看到自己的新的容颜。这一事实震惊了Donchian,所以他也采用了这个说法。(小编也听说过,养成一个新的习惯需要21天嘛)

    实现这个策略,最好采用按分钟回测,这样可以准确的捕捉日内的买卖点,否则等日线的收盘价出来,说不定已经离突破很远了。同时请注意,在以往国外的实战当中,主要是在纽约和芝加哥的场内期货交易的,期货可以做多也可以做空,但是国内的股票只能买入和卖出,因此我们只能做向上突破。

    止损

    有了唐奇安通道,我们有了买入和卖出的依据了, 那么止损是干什么的呢?其实止损提出的初衷是,如果某笔交易是亏损的交易,造成的损失不要超过总仓位的k%。在完整的海龟系统里面,海龟用了一系列的公式进行仓位比例的计算,具体的内容可以参考下一节。

    完整的海龟交易系统

    完整的海龟交易系统包含以下内容:
    1、市场:原版海龟选择交易纽约和芝加哥的场内期货。筛选标准则是高流动性,我大A股市场当然也符合这个标准啦。

    2、仓位:这可以说是海龟交易系统最核心的部分。Richard Dennis期望通过市场的波动性水平来管理仓位。其构建了指数N来衡量波动性水平。指数的构建为以下四步
    (注:如果暂时不能理解下面的公式,完全不用担心,这些都在代码中体现出来,大家可以在代码的实际使用中搞明白这些麻烦的公式)。

    (1)True Range

    TrueRange=Maximum(H−L,H−PDC,PDC−L)
    TrueRange=Maximum(H−L,H−PDC,PDC−L)
    公式中,True Range表示一天内的波动量,H为当日日内最高价,L为当日日内最低价,PDC为前一日收盘价。

    (2)N

    N=19∗PDN+TR20
    N=19∗PDN+TR20
    公式中,TR为True Range,即一天内波动量,PDN为前一日的N值。此公式的真是含义为计算之前20天(包括今天在内)的N的平均值

    (3)Dollar Volatility

    DollarVolatility=N∗DollarsPerPoint
    DollarVolatility=N∗DollarsPerPoint
    公式中,Dollar Volatility指的是波动的价格,Dollars per Point指的是标的股票每波动一个最小单位,1手股票的总价格变化量。在国内最小变化量是0.01元,1手是100股。所以Dollars per Point就是0.01×100=1

    (4)Unit

    Unit=1%ofAccountMarketDollarVolatility
    Unit=1%ofAccountMarketDollarVolatility
    公式中,Unit即为我们买卖的单位,1% of Account是总资产的1%,Market Dollar Volatility就是我们之前算出的Dollar Volatility,通过此公式计算出的Unit就是我们要买入的单位数量。此公式的意义是在一般情况下(市场波动率不大的时候),如果买入1Unit单位的资产,当天震幅使得总资产的变化不超过1%

    3、入市:海龟将所有资金分为两部分,一部分资金按系统一执行,一部分资金按系统二执行
    系统一
    (1)若当前价格高于过去20日的最高价,则买入一个Unit(注意是分钟回测)
    (2)加仓:若股价在上一次买入(或加仓)的基础上上涨了0.5N,则加仓一个Unit
    系统二
    与系统一相一致,但当如破55日最高价时才购买
    (1)若当前价格高于过去55日的最高价,则买入一个Unit(注意是分钟回测)
    (2)加仓:若股价在上一次买入(或加仓)的基础上上涨了0.5N,则加仓一个Unit
    Example:若某只股票A的N为2,20日最高价为100
    则当股价突破100时买入一个Unit,当股价突破100+0.5×2=101时加仓一个Unit,当股价突破101+0.5×2=102时加仓一个Unit。

    4、止损:即损失达到多少时就一定要卖出现有仓位。海龟交易系统规定,当价格比最后一次买入价格下跌2N时,则卖出全部头寸止损(也就是,在一般情况下,损失不会超过2%)。

    5、止盈:
    系统一
    当股价跌破10日内最低价时(10日唐奇安通道下沿),清空头寸结束本次交易
    系统二
    当股价跌破20日内最低价时(20日唐奇安通道下沿),清空头寸结束本次交易

    6、技巧:资金的调整。开始时设定两个比例:Loss和Adjust。若交易结束后损失的资金占总资金比例大于Loss,则今后只用现有投资资金的Adjust比例。
    Example:若初始资金为100万,设定Loss=80%,Adjust=90%。则当总资产低于100×80%=80万时,进行一次资金调整,以后只使用80×90%=72万的资金用于投资行为

    # coding=utf-8 from __future__ import print_function, absolute_import, unicode_literals import numpy as np import pandas as pd try: import talib except: print('请安装TA-Lib库') from gm.api import * ''' 本策略通过计算CZCE.FG801和SHFE.rb1801的ATR.唐奇安通道和MA线,并: 上穿唐奇安通道且短MA在长MA上方则开多仓,下穿唐奇安通道且短MA在长MA下方则开空仓 若有 多/空 仓位则分别: 价格 跌/涨 破唐奇安平仓通道 上/下 轨则全平仓位,否则 根据 跌/涨 破持仓均价 -/+ x(x=0.5,1,1.5,2)倍ATR把仓位 回测数据为:CZCE.FG801和SHFE.rb1801的1min数据 回测时间为:2017-09-15 09:15:00到2017-10-01 15:00:00 ''' def init(context): # context.parameter分别为唐奇安开仓通道.唐奇安平仓通道.短ma.长ma.ATR的参数 context.parameter = [55, 20, 10, 60, 20] context.tar = context.parameter[4] # context.goods交易的品种 context.goods = ['CZCE.FG801', 'SHFE.rb1801'] # context.ratio交易最大资金比率 context.ratio = 0.8 # 订阅context.goods里面的品种, bar频率为1min subscribe(symbols=context.goods, frequency='60s', count=101) # 止损的比例区间 def on_bar(context, bars): bar = bars[0] symbol = bar['symbol'] recent_data = context.data(symbol=symbol, frequency='60s', count=101, fields='close,high,low') close = recent_data['close'].values[-1] # 计算ATR atr = talib.ATR(recent_data['high'].values, recent_data['low'].values, recent_data['close'].values, timeperiod=context.tar)[-1] # 计算唐奇安开仓和平仓通道 context.don_open = context.parameter[0] + 1 upper_band = talib.MAX(recent_data['close'].values[:-1], timeperiod=context.don_open)[-1] context.don_close = context.parameter[1] + 1 lower_band = talib.MIN(recent_data['close'].values[:-1], timeperiod=context.don_close)[-1] # 计算开仓的资金比例 percent = context.ratio / float(len(context.goods)) # 若没有仓位则开仓 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: # 计算长短ma线.DIF ma_short = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[2] + 1))[-1] ma_long = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[3] + 1))[-1] dif = ma_short - ma_long # 获取当前价格 # 上穿唐奇安通道且短ma在长ma上方则开多仓 if close > upper_band and (dif > 0): order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market, position_side=PositionSide_Long) print(symbol, '市价单开多仓到比例: ', percent) # 下穿唐奇安通道且短ma在长ma下方则开空仓 if close < lower_band and (dif < 0): order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market, position_side=PositionSide_Short) print(symbol, '市价单开空仓到比例: ', percent) elif position_long: # 价格跌破唐奇安平仓通道全平仓位止损 if close < lower_band: order_close_all() print(symbol, '市价单全平仓位') else: # 获取持仓均价 vwap = position_long['vwap'] # 获取持仓的资金 money = position_long['cost'] # 获取平仓的区间 band = vwap - np.array([200, 2, 1.5, 1, 0.5, -100]) * atr grid_percent = float(pd.cut([close], band, labels=[0, 0.25, 0.5, 0.75, 1])[0]) * percent # 选择现有百分比和区间百分比中较小的值(避免开仓) target_percent = np.minimum(money / context.account().cash['nav'], grid_percent) if target_percent != 1.0: print(symbol, '市价单平多仓到比例: ', target_percent) order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market, position_side=PositionSide_Long) elif position_short: # 价格涨破唐奇安平仓通道或价格涨破持仓均价加两倍ATR平空仓 if close > upper_band: order_close_all() print(symbol, '市价单全平仓位') else: # 获取持仓均价 vwap = position_short['vwap'] # 获取持仓的资金 money = position_short['cost'] # 获取平仓的区间 band = vwap + np.array([-100, 0.5, 1, 1.5, 2, 200]) * atr grid_percent = float(pd.cut([close], band, labels=[1, 0.75, 0.5, 0.25, 0])[0]) * percent # 选择现有百分比和区间百分比中较小的值(避免开仓) target_percent = np.minimum(money / context.account().cash['nav'], grid_percent) if target_percent != 1.0: order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market, position_side=PositionSide_Short) print(symbol, '市价单平空仓到比例: ', target_percent) 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='strategy_id', filename='main.py', mode=MODE_BACKTEST, token='token_id', backtest_start_time='2017-09-15 09:15:00', backtest_end_time='2017-10-01 15:00:00', backtest_adjust=ADJUST_PREV, backtest_initial_cash=10000000, backtest_commission_ratio=0.0001, backtest_slippage_ratio=0.0001)

    阅读更多
  • J

    @jmcoin 效率真高👋 👋 👋

    阅读更多