量化交易之海龟策略

版权声明:随意转载 https://blog.csdn.net/qscqesze/article/details/79965820

量化交易之海龟策略

代码只能保证运行在ricequant上

海龟策略这里我就不着重介绍,感兴趣可以去买书自己看。

海龟法则的加仓原则是定义好一个小单位(Unit),使得该仓位的预期价值波动与总净资产的1%对应。

TrueRange=Max(High−Low, High−PreClose, PreClose−Low)

N =(前19日的N值之和+当时的TrueRange)/20

其中,High表示当日最高价,Low表示当日最低价,PreClose表示前一日收盘价。

我们可以从定义上看出,N值确实能很恰当地表达该资产在价格上的最近波动幅度。

这样,一个Unit就应该是这样计算出来的:

Unit = (1%*Total_net)/N, total_net就是总资产净值

可以看出,一个Unit的资产的价格波动幅度 = 总净资产的1%

  1. 什么时候建仓

建仓的动作来自于趋势突破信号的产生。如果当前价格冲破上轨,就产生了一个买的建仓信号,如果当前价格跌破下轨,就产生了一个卖空的建仓信号(如果该市场支持卖空,某些数字资产市场是支持借币卖空的!)

初始建仓的大小 = 1个Unit

  1. 什么时候加仓

如果开的底仓是多仓且资产的价格在上一次建仓(或者加仓)的基础上又上涨了0.5N,就再加一个Unit的多仓;

如果开的底仓是空仓且资产的价格在上一次建仓(或者加仓)的基础上又下跌了0.5N,就再加一个Unit的空仓。

我们看到,海龟策略其实是一个追涨杀跌的策略的。

  1. 怎么做动态止损

如果开的底仓是多仓且资产的价格在上一次建仓(或者加仓)的基础上又下跌了2N,就卖出全部头寸止损;

如果开的底仓是空仓且资产的价格在上一次建仓(或者加仓)的基础上又上涨了2N,就buy cover全部的头寸止损。

当然,用户可以自定义动态止损方案,比如下跌了0.5N就开始部分平仓,而不用等到下跌了2N后才匆忙一次性清仓,毕竟冲击成本摆在那里。

  1. 怎么做止盈,可以自定义动态止盈吗

海龟法则里面,止盈信号是这样产生的:

如果开的底仓是多仓且当前资产价格跌破了10日唐奇安通道的下轨,就清空所有头寸结束策略;

如果开的底仓是空仓且当前资产价格升破了10日唐奇安通道的上轨,就清空所有头寸结束策略。

当然,用户可以自定义动态止盈方案,比如总净资产/初始净资产>1.5, 就止盈离场。

下面是我实现的代码,较常规的海龟策略而言,我增加了每次开盘前有一个筛选股票的策略,我只会在市值最大的几只股票进行操作。

10年回撤效果。。。可喜可贺,跑过了沪深300指数,调整一下参数,说不定结果会很好看:)

这里写图片描述

# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
import numpy as np
import pandas as pd
import talib
import math

# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
    # 在context中保存全局变量
    context.s = []
    context.vis = {}
    context.last_buy_price = {} 
    #上一次买入价格
    context.hold_flag = {}
    #False 
    #是否持有头寸标志,即是否买入
    context.limit_unit = 4 
    #最多买入单元数
    context.unit = {}#0 
    #现在买入一单元股数
    context.add_time = {}#0 
    #买入次数 最多四次
    context.long_time = 55
    context.short_time = 20
    context.ten_time = 10

def CalcATR(high,low,close):
    TR_List = []
    for i in range(1,min(21,len(high),len(close))):
        TR = max(high[i]-low[i],abs(high[i]-close[i-1]),abs(close[i-1]-low[i]))
        TR_List.append(TR)
    ATR = np.array(TR_List).mean()
    return ATR

def CalcUnit(perValue,ATR):#计算unit

    return int((perValue/ATR)/100)*30
    # 乘了个系数,莽

def IN_OR_OUT(high,low,price): #判断入场还是离场
    up = max(high)
    down = min(low) 
    if price>up:
        return 1
    elif price<down:
        return -1
    else:
        return 0 

def Add_OR_Stop(price,lastprice,ATR):
    if price >= lastprice + 0.5*ATR:
        return 1
    elif price <= lastprice - 0.5*ATR:
        return -1
    else:
        return 0    

# before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
# 选股策略,选三个满足特征的几个,然后来进行排序
def before_trading(context): # 获得stock list
    num_stocks = 5
    fundamental_df = get_fundamentals(
        query(
            fundamentals.eod_derivative_indicator.pb_ratio,
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.eod_derivative_indicator.peg_ratio,
        )
        .filter(
            fundamentals.eod_derivative_indicator.pe_ratio<60
        )
        .filter(
            fundamentals.eod_derivative_indicator.pb_ratio<5
        )
        .filter(
            fundamentals.eod_derivative_indicator.peg_ratio<0.9
        )
        .order_by(
            fundamentals.eod_derivative_indicator.market_cap.desc()
        ).limit(
            num_stocks
        )
    )
    '''
    fundamental_df = get_fundamentals(
        query(
            fundamentals.eod_derivative_indicator.market_cap
        ).filter(
            fundamentals.eod_derivative_indicator.market_cap<5e10
        ).order_by(
            fundamentals.eod_derivative_indicator.market_cap.asc()   
        ).limit(
            num_stocks
        )
    )
    '''
    drop_list = []
    for stock in context.s:
        if context.add_time.get(stock,0) == 0:
            drop_list.append(stock)
    for stock in drop_list:
        init_stock(context,stock)
    if len(context.s) < 20:
        for stock in fundamental_df:
            if stock not in context.vis:
                context.s.append(stock)
                context.vis[stock] = 1
    logger.info(str(context.s))


# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
def handle_bar(context, bar_dict):
    # 开始编写你的主要的算法逻辑
    stock_list = []
    for stock in context.s:
        stock_list.append(stock)
    for stock in stock_list:
        do_trade(context,stock)

def init_stock(context,stock):
    context.s.remove(stock)
    if stock in context.last_buy_price:
        del context.last_buy_price[stock]
    if stock in context.hold_flag:
        del context.hold_flag[stock]
    if stock in context.unit:
        del context.unit[stock] 
    if stock in context.add_time:
        del context.add_time[stock]
    if stock in context.vis:
        del context.vis[stock]

def do_trade(context,stock):
    high_price = history_bars(stock,context.short_time+1, '1d', 'high')
    low_price = history_bars(stock,context.short_time+1, '1d', 'low')
    close_price = history_bars(stock,context.short_time+2, '1d', 'close')
    close_price_atr = close_price[:-1]

    high_price_55 = history_bars(stock,context.long_time+1, '1d', 'high')
    low_price_55 = history_bars(stock,context.long_time+1, '1d', 'low')
    high_price_10 = history_bars(stock,context.ten_time+1, '1d', 'high')
    low_price_10 = history_bars(stock,context.ten_time+1, '1d', 'low')
    price_minute = history_bars(stock,context.short_time,'1m','close')
    price = price_minute[-1] #股票最新价格
    # 计算ATR
    ATR = CalcATR(high_price,low_price,close_price_atr)
    out = IN_OR_OUT(high_price_55,low_price_55,price) #判断入场还是离场

    if out==1 and context.hold_flag.get(stock,False)==False: #入场
        value = context.portfolio.cash*0.01  # 我的资金的1%
        context.unit[stock] = CalcUnit(value,ATR)
        order_shares(stock, context.unit[stock])
        context.add_time[stock]=1
        context.hold_flag[stock]=True
        context.last_buy_price[stock]=price
    elif out==-1 and context.hold_flag.get(stock,False) ==True: #离场
        order_percent(stock,-1)
        init_stock(context,stock) #重新初始化

    #判断加仓还是止损
    if context.hold_flag.get(stock,False)==True :
        temp = Add_OR_Stop(price,context.last_buy_price.get(stock,0),ATR)
        if temp==1 and context.add_time.get(stock,4) < context.limit_unit:#加仓
            order_shares(stock,context.unit[stock])
            context.last_buy_price[stock]=price
            context.add_time[stock]+=1
        elif temp==-1:
            if context.add_time.get(stock,0) == 1:
                order_percent(stock,-1)
                init_stock(context,stock)
            else:
                order_shares(stock,context.unit.get(stock,0))
                context.add_time[stock]-=1


# after_trading函数会在每天交易结束后被调用,当天只会被调用一次
def after_trading(context):
    pass
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页