• 鳄鱼法则


    import numpy as np
    def initialize(context):
        g.up_price = {} #向上碎形最高价
        g.low_price = {} #向下碎形最低价
        g.up_fractal_exists = {} #判断有效向上碎形
        g.down_fractal_exists = {} #判断有效向下碎形
        g.AO_index = {} #存放连续的AO指标数据
        g.cal_AC_index = {} #计算AC指标中转存储
        g.AC_index = {} #存放连续的AC指标数据
        g.amount = {} #满仓仓位
        g.stock = get_index_stocks('000300.XSHG')
        g.buy_stock = []
        set_benchmark('000300.XSHG')
        g.month = context.current_dt.month
        run_monthly(select_universe,1,'open')
    
    #重置全局变量
    def reset_global():
        g.up_price = {} #向上碎形最高价
        g.low_price = {} #向下碎形最低价
        g.up_fractal_exists = {} #判断有效向上碎形
        g.down_fractal_exists = {} #判断有效向下碎形
        g.AO_index = {} #存放连续的AO指标数据
        g.cal_AC_index = {} #计算AC指标中转存储
        g.AC_index = {} #存放连续的AC指标数据
        g.amount = {} #满仓仓位
        g.buy_stock = []
    
    def initial_stock_global(stock):
        g.up_price[stock] = 0
        g.low_price[stock] = 0
        g.up_fractal_exists[stock] = False
        g.down_fractal_exists[stock] = False #判断有效向下碎形
        g.AO_index[stock] = [0] #存放连续的AO指标数据
        g.cal_AC_index[stock] = [0]  #计算AC指标中转存储
        g.AC_index[stock] = [0] #存放连续的AC指标数据
        g.amount[stock] = 0 #满仓仓位
    
    #轮换选股后清空持仓
    def reset_position(context):
        for stock in g.buy_stock:
            order_target(stock,0)
            log.info("sell %s for reset position"%stock)
    #选股
    def select_universe(context):
        #每三个月操作一次
        month = context.current_dt.month
        if month%6 != g.month%6:
            return
        #清空全局变量
        reset_position(context)
        reset_global()
        hist = history(30,'1d','close',g.stock,df = False)
        for stock in g.stock:
            if is_sleeping_alligator(stock,hist,20):
                g.buy_stock.append(stock)
                #初始化该股票全局变量
                initial_stock_global(stock)
        print g.buy_stock
        return None
    
    #睡着的鳄鱼
    def is_sleeping_alligator(stock,hist,nday):
        for i in range(nday):
            if is_struggle(stock,hist,i) == False:
                return False
        return True
    
    #均线纠缠,BRG三线非常接近
    def is_struggle(stock,hist,delta):
        blue_line = hist[stock][-21-delta:-8-delta].mean()
        red_line = hist[stock][-13-delta:-5-delta].mean()
        green_line = hist[stock][-8-delta:-3-delta].mean()
        if abs(blue_line/red_line-1)<0.02 and abs(red_line/green_line-1)<0.02:
            return True
        else:
            return False
    
    #判断 向上 或 向下 碎形
    def is_fractal(stock,direction):
        hist = history(5,'1d',direction,[stock],df = False)
        if direction == 'high'
        and hist[stock][2] > hist[stock][0]
        and hist[stock][2] > hist[stock][1]
        and hist[stock][2] > hist[stock][3]
        and hist[stock][2] > hist[stock][4]:
            g.up_price[stock] = hist[stock][2]
            return True
        elif direction == 'low'
        and hist[stock][2] < hist[stock][0]
        and hist[stock][2] < hist[stock][1]
        and hist[stock][2] < hist[stock][3]
        and hist[stock][2] < hist[stock][4]:
            g.low_price[stock] = hist[stock][2]
            return True
        return False
    
    #通过比较碎形与红线位置,判断碎形是否有效
    def is_effective_fractal(stock, direction):
        if is_fractal(stock,direction):
            hist = history(13,'1d','close',[stock],df = False)
            red_line = hist[stock][:-5].mean()
            close_price = hist[stock][-1]
            if direction == 'high':
                if close_price > red_line:
                    g.up_fractal_exists[stock] = True
                else:
                    g.up_fractal_exists[stock] = False
            elif direction == 'low':
                if close_price < red_line:
                    g.down_fractal_exists[stock] = True
                else:
                    g.down_fractal_exists[stock] = False
    
    #N日内最高价格的N日线
    def nday_high_point(stock,n):
        hist = history(2*n,'1d','high',[stock],df = False)[stock]
        high_point = []
        for i in range(n):
            high_point.append(max(hist[-5-i:-1-i]))
        return np.array(high_point).mean()
    
    #N日内最低价格的N日线
    def nday_low_point(stock,n):
        hist = history(2*n,'1d','low',[stock],df = False)[stock]
        low_point = []
        for i in range(n):
            low_point.append(max(hist[-5-i:-1-i]))
        return np.array(low_point).mean()
    
    #AO=5日内(最高-最低)/2的5日移动平均-34日内(最高-最低)/2的34日移动平均
    def AO_index(stock):
        g.AO_index[stock].append(nday_high_point(stock,5)/2 + nday_low_point(stock,5)/2
                          - nday_high_point(stock,34)/2 - nday_low_point(stock,34)/2)
        return None
    
    #AO-AO的5日平均值的5日平均
    def AC_index(stock):
        AO_index(stock)
        if len(g.AO_index[stock]) >= 5:
            g.cal_AC_index[stock].append(g.AO_index[stock][-1] - np.array(g.AO_index[stock][-5:]).mean())
            if len(g.cal_AC_index[stock]) >=5:
                g.AC_index[stock].append(np.array(g.cal_AC_index[stock][-5:]).mean())
    
    #判断序列n日上行
    def is_up_going(alist,n):
        if len(alist) < n:
            return False
        for i in range(n-1):
            if alist[-(1+i)] <= alist[-(2+i)]:
                return False
        return True
    
    #判断序列n日下行
    def is_down_going(alist,n):
        if len(alist) < n:
            return False
        for i in range(n-1):
            if alist[-(1+i)] >= alist[-(2+i)]:
                return False
        return True
    
    #碎形被突破
    def active_fractal(stock,direction):
        close_price = history(1,'1d','close',[stock],df=False)[stock][0]
        if direction == 'up' and close_price > g.up_price[stock]:
            return True
        elif direction == 'down' and close_price < g.low_price[stock]:
            return True
        return False
    
    #进场,初始仓位
    def set_initial_position(stock,context):
        close_price = history(1,'1d','close',[stock],df=False)[stock][0]
        g.amount[stock] = context.portfolio.cash/close_price/len(g.buy_stock)*3
        order(stock, g.amount[stock])
        log.info("buying %s 股数为 %s"%(stock,g.amount[stock]))
        g.down_fractal_exists[stock] = False
    
    #卖出
    def sell_all_stock(stock,context):
        order_target(stock,0)
        log.info("selling %s"%stock)
        g.up_fractal_exists[stock] = False
    
    #加仓
    def adjust_position(stock,context,position):
        order(stock,g.amount[stock]*position)
        log.info("adjust position buying %s 股数为 %s"%(stock,g.amount[stock]*position))
    
    # 计算股票前n日收益率
    def security_return(days,security_code):
        hist1 = attribute_history(security_code, days + 1, '1d', 'close',df=False)
        security_returns = (hist1['close'][-1]-hist1['close'][0])/hist1['close'][0]
        return security_returns
    
    # 止损,根据前n日收益率
    def conduct_nday_stoploss(context,security_code,days,bench):
        if  security_return(days,security_code)<= bench:
            for stock in g.buy_stock:
                order_target_value(stock,0)
                log.info("Sell %s for stoploss" %stock)
            return True
        else:
            return False
    
    # 计算股票累计收益率(从建仓至今)
    def security_accumulate_return(context,data,stock):
        current_price = data[stock].price
        cost = context.portfolio.positions[stock].avg_cost
        if cost != 0:
            return (current_price-cost)/cost
        else:
            return None
    
    # 个股止损,根据累计收益
    def conduct_accumulate_stoploss(context,data,stock,bench):
        if security_accumulate_return(context,data,stock) != None
        and security_accumulate_return(context,data,stock) < bench:
            order_target_value(stock,0)
            log.info("Sell %s for stoploss" %stock)
            return True
        else:
            return False
    
    # 个股止盈,根据累计收益
    def conduct_accumulate_stopwin(context,data,stock,bench):
        if security_accumulate_return(context,data,stock) != None
        and security_accumulate_return(context,data,stock) > bench:
            order_target_value(stock,0)
            log.info("Sell %s for stopwin" %stock)
            return True
        else:
            return False
    
    def handle_data(context,data):
        #大盘止损
        if conduct_nday_stoploss(context,'000300.XSHG',3,-0.03):
            return
        for stock in g.buy_stock:
            #个股止损
            if conduct_accumulate_stopwin(context,data,stock,0.3)
            or conduct_accumulate_stoploss(context,data,stock,-0.1):
                return
            #计算AO,AC指标
            AC_index(stock)
            #空仓时,寻找机会入场
            if context.portfolio.positions[stock].amount == 0:
                #计算向上碎形
                is_effective_fractal(stock,'high')
                #有效向上碎形存在,并被突破,买入
                if g.up_fractal_exists and active_fractal(stock,'up'):
                    close_price = history(5, '1d', 'close', [stock],df = False)
                    if is_up_going(g.AO_index[stock],5)
                    and is_up_going(g.AC_index[stock],3)
                    and is_up_going(close_price[stock],2):
                        set_initial_position(stock,context)
            #有持仓时,加仓或离场
            else:
                #计算向下碎形
                is_effective_fractal(stock,'low')
                #出场条件1:有效向下碎形存在,并被突破,卖出
                if g.down_fractal_exists and active_fractal(stock,'down'):
                    sell_all_stock(stock,context)
                    return
                #出场条件2:
                #加仓10%:AO,AC同时5日上行,且收盘价走高
                # if is_up_going(g.AO_index[stock],5)
                # and is_up_going(g.AC_index[stock],3)
                # and is_up_going(close_price[stock],2):
                #     adjust_position(stock,context,0.1)
                # #减仓10%:AO,AC同时3日下行,且收盘价走低
                # if is_down_going(g.AO_index[stock],5)
                # and is_down_going(g.AC_index[stock],3)
                # and is_down_going(close_price[stock],2):
                #     adjust_position(stock,context,-0.1)
    

      

    简要介绍

    1.选股

    • 选择沪深300指数成分股
    • 沉睡的鳄鱼,RBG三线纠缠。(选择连续20交易日处于沉睡状态的股票,建立buy_stock池)
    • 每6个月更新股票池
    • benchmark沪深300指数

    2.入场

    • 存在有效碎形
    • 有效碎形被突破
    • AO指标连续5日上行
    • AC指标连续3日上行
    • 收盘价高于前一日收盘价
    • 按g.amount=总资金/股票池股数×乘数因子3买入。

    3.止损&止盈

    • 大盘3日累计收益率下跌3%,全部股票清仓
    • 个股累计收益率(以成本价为基准)超过30%,全部卖出
    • 个股累计收益率下跌10%,全部卖出

    4.加仓&减仓(感觉用处不大,暂没有使用,源代码保留在注释里)

    • AO连续5日上行,AC连续3日上行加仓10%
    • AO连续5日下跌,AC连续3日下跌减仓10%

    5.退出

    • 存在有效向下碎形
    • 向下碎形被突破
    • 全部卖出

    小结一下

    关于组合仓位控制
    股票池组合操作对于仓位控制的要求比较严格。目前这方面还没有太多系统的想法,包括建仓比例,调仓以及不同股票的仓位配置,资金利用效率等等。
    举例:g.amount在赋值时,简单的认为根据(总资金/buy_stock股数)×乘数因子 对资金配比。乘数因子是避免不符合条件的股票太多导致仓位较低,影响资金利用效率。
    个人感觉,可以根据市值、pe或则其他体现每只持仓股票差异的因素来进行仓位管理,这方面有好的建议的朋友可以留言一起探讨。

    止损条件
    止损和止盈条件纯属个人风格吧。也是每一个策略里必然会加上的。15年至今的回测结果来看,回撤控制的比较好。当然也就牺牲了一些较大获利的可能性。

  • 相关阅读:
    一个IT工薪族的4年奋斗成果
    一个IT工薪族的4年奋斗成果
    【VBA】制作散点图及打标签VBA
    【VBA】合并多个excel文件
    【统计分析】ROC曲线
    【ARDUINO】HC-05蓝牙不配对问题
    【ARDUINO】串口无法打开问题
    【ARDUINO】蓝牙(HC-05)透传
    【Raspberry pi+python+mysql】红外传感器-发邮件-存数据库
    【Raspberry Pi】crontab 定时任务
  • 原文地址:https://www.cnblogs.com/xzqpy/p/11955570.html
Copyright © 2020-2023  润新知