请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3351406 新帖:24

二八轮动小市值优化版 v2.0.7 [更新于2016.11.16]

交易资深人士发表于:6 月 25 日 18:00回复(1)

感谢各位大拿小拿提供策略和代码,增加了交易统计,统计代码也是社区里的人提供的,站在巨人的肩膀上,包装优化了下,贴出,供大家参考,总是拿来也不好意思。另外说一下,如果策略选择,选股,建仓,调仓,止损,统计等等全部都做成一个模块,后期随意搭配起来也许会方便很多。

策略说明:

小市值择时买卖

配置指定频率的调仓日,在调仓日每日指定时间,计算沪深300指数和中证500指数当前的20日涨幅,如果2个指数的20日涨幅有一个为正,则进行选股调仓,之后如此循环往复。

止损策略:每日指定时间,计算沪深300指数和中证500指数当前的20日涨幅,如果2个指数涨幅都为负,则清仓,重置调仓计数,待下次调仓条件满足再操作。

运行说明:

1. 在研究里建立文件tradestat.py,拷贝下面研究里第一格的所有代码到tradestat.py,再保存,使用方式的代码不需要拷贝
2. 使用分钟回测,否则不会有交易
3. 每次更新前请务必看下更新日志,部分版本的更新需要一起更新tradestat.py

注:
1. 给出的策略代码并非最优参数,各位请自行调整参数测试吧
2. 此策略代码仅供学习参考,交易有风险,实盘需谨慎,特此提醒

待改进:实时根据资金动态调整买入股票数目

更新:

2016.11.16

v2.0.7
增加根据28指数值实时止损,效果暂不理想,默认关闭
感谢@零零发 的分享,完善根据大盘价格止损,改为根据160日高低价格进行条件止损,回测降低了不少
优化日志,更易读
感谢@ordo,优化选股代码
调整默认参数,并非最优,最优我也不知道:-)
注:

  1. 默认3日3股评分大盘价格及三黑鸦止损
  2. 持股数量一般会影响策略波动性,数量太少,策略波动较大,建议股票数目 >= 3,然后调整
    参数达到一个好的配置
  3. 三黑鸦会降低回测,同时收益也会降低

2016.08.31

v2.0.6
完善三黑鸦判定算法,放宽判定条件,在前日三黑鸦形态下,当日为跌的分钟计数达到指定值,则进行止损,此方法主要为了增加三黑鸦的有效性

注:部分同学测试16年收益低,是因为6月8号左右的三黑鸦,估计v2.0.5判定有点严格

2016.08.30

v2.0.5
根据百度百科描述修正三黑鸦算法,根据前4日数据判断,在三黑鸦形态下当日为跌的分钟计
数达到指定值后,进行止损,修正潜在bug

注:个人认为针对大盘判断三黑鸦效果并不好,首先有效三只乌鸦难以判断,准确率实际来看也不好,其次,分析历史行情看一般大盘出现三只乌鸦的时候,已经严重滞后了,使用其他止损方式可能会更好

2016.08.19

v2.0.4
修改止盈止损阈值的计算为根据调仓间隔日期获取,比如5日调仓则获取历史3日的幅度

2016.08.17

v2.0.3
拆分三黑鸦和指数价格止损及配置,优化大盘三黑鸦及指数价格止损,避免每分钟反复获取数据处理,提高回测效率

2016.08.16

v2.0.2
修复部分小bug,感谢 @michaeljrqiu @射手摩羯座的提醒

v2.0.1

  1. 完善了平仓的盈亏统计,主要针对部分成交,另外修正了部分成交的平仓导致的最高价缓存被删除的问题
  2. 更新了tradestat的统计调用函数,用以支持对部分成交进行盈亏统计

更新说明:需要更新tradestat.py,从下面的研究里复制新的代码并替换

止盈止损阈值的获取速度待优化。

2016.08.15

v2.0.0
感谢@az大神的策略分享 https://www.joinquant.com/post/2035?tag=algorithm
增加EPS选股,选股评分,大盘三黑鸦及高低价止损,个股止盈止损,全部可选配置
默认参数配置当前只为保留1.2.8版本的收益和回撤,如果想进行其他调整,请自行调配参数

注:此版本几乎全部实现了@az在其帖子中描述的策略,可自行配置参数严格根据@az的描述的调试,至于收益回撤的问题,个人估计是选股的问题,具体原因我也不清楚 ;-),有需求还请咨询@az大神吧。

v1.2.8
完善买卖接口,聚宽对于部成部撤的报单,返回的报单状态为已撤,故修改为根据报单成交量来判断报单是否成功,同期收益回撤不变

2016.08.13

v1.2.7
优化买卖接口,解决涨跌停股票创建报单成功但被取消导致不必要的后处理,同期收益回撤不变

2016.07.19

v1.2.6
感谢 @Special 的指正,修正了胜率统计的bug,避免在股票卖出失败的时候多进行了一次统计,交易次数减少了,同期胜率降低了1%,收益回撤等其他不变,策略及tradestat.py 已更新。
更新说明:需要更新tradestat.py,从下面的研究里复制新的代码并替换

2016-07-08 15:10:00 - INFO - ------------绩效报表------------
2016-07-08 15:10:00 - INFO - 交易次数: 156, 盈利次数: 108, 胜率: 69.2%
2016-07-08 15:10:00 - INFO - 单次盈利最高: 600593.XSHG, 盈利比例: 107.56%
2016-07-08 15:10:00 - INFO - 单次亏损最高: 600719.XSHG, 亏损比例: -15.32%
2016-07-08 15:10:00 - INFO - 总资产: 1370639.74, 本金: 100000.0, 盈利: 1270639.74, 盈亏比率:1270.63974%
2016-07-08 15:10:00 - INFO - --------------------------------

2016.07.14

v1.2.5
增加跌停股票过滤,多谢@沙米建议,同期提高了不少收益率,提高了胜率,降低了最大单股亏损,回撤基本不变

2016-07-08 15:10:00 - INFO - ------------绩效报表------------
2016-07-08 15:10:00 - INFO - 交易次数: 185, 盈利次数: 130, 胜率: 70.0%
2016-07-08 15:10:00 - INFO - 单次盈利最高: 600593.XSHG, 盈利比例: 107.56%
2016-07-08 15:10:00 - INFO - 单次亏损最高: 600719.XSHG, 亏损比例: -15.32%
2016-07-08 15:10:00 - INFO - 总资产: 1370639.74, 本金: 100000.0, 盈利: 1270639.74, 盈亏比率:1270.63974%
2016-07-08 15:10:00 - INFO - --------------------------------

v1.2.4
完善日志输出,打印策略配置参数,调整主要日志为中文

2016.07.13

v1.2.3
完善ST及停牌股票的过滤(来自菜菜午出头),优化日志

2016.07.12

v1.2.2
优化增幅计算代码

v1.2.1
改进黑名单配置,感谢@az的指正,修正了创业板股票判断的bug,策略已更新

v1.2.0
感谢 @zw @沙米 的完善,在其基础上增加了过滤控制,可选择配置市盈率选股、过滤创业板及过滤黑名单,设置了pe参数,增加了注释,因为配置了pe选股及过滤了创业板,收益有所降低,但是回撤也相应降低了,策略已更新
注:黑名单有时效性,回测已注释

2016-07-08 15:10:00 - INFO - ------------绩效报表------------
2016-07-08 15:10:00 - INFO - 交易次数: 188, 盈利次数: 128, 胜率: 68.0%
2016-07-08 15:10:00 - INFO - 单次盈利最高: 600593.XSHG, 盈利比例: 107.56%
2016-07-08 15:10:00 - INFO - 单次亏损最高: 600656.XSHG, 亏损比例: -30.41%
2016-07-08 15:10:00 - INFO - 总资产: 1166076.61, 本金: 100000.0, 盈利: 1066076.61, 盈亏比率:1066.07661%
2016-07-08 15:10:00 - INFO - --------------------------------

2016.07.02
修正调仓日因持仓股票涨停被过滤导致本该继续持有的股票被卖出的问题,收益回撤影响不大,提高了单股盈利
说明,当前调仓因股票停牌不能卖出的时候会继续持有,始终保持指定数目的股票持仓

2016-06-28 15:10:00 - INFO - ------------绩效报表------------
2016-06-28 15:10:00 - INFO - 交易次数: 199, 盈利次数: 144, 胜率: 72.0%
2016-06-28 15:10:00 - INFO - 单次盈利最高: 000004.XSHE, 盈利比例: 139.99%
2016-06-28 15:10:00 - INFO - 单次亏损最高: 300029.XSHE, 亏损比例: -17.36%
2016-06-28 15:10:00 - INFO - 总资产: 1323435.9, 本金: 100000.0, 盈利: 1223435.9, 盈亏比率:1223.4359%

2016.07.01
根据@zx1967的反馈,调整了选股数目大小(g.selected_stock_cnt = 100,其实可以更大),尽量避免数目过小而恰巧全部过滤掉以致最终可买股票为空,结果收益更高了,回撤差不多,回测已更新

2016.06.30
感谢 @莫邪的救赎 的建议,修改为run_daily执行,主要是提高了回测速度,回测时间缩短了近一半

#coding=utf-8

from kuanke.user_space_api import *

class trade_stat():
    def __init__(self):
        self.trade_total_count = 0
        self.trade_success_count = 0
        self.statis = {'win': [], 'loss': []}
        
    def reset(self):
        self.trade_total_count = 0
        self.trade_success_count = 0
        self.statis = {'win': [], 'loss': []}
    
    # 记录交易次数便于统计胜率
    # 卖出成功后针对卖出的量进行盈亏统计
    def watch(self, stock, sold_amount, avg_cost, cur_price):
        self.trade_total_count += 1
        current_value = sold_amount * cur_price
        cost = sold_amount * avg_cost

        percent = round((current_value - cost) / cost * 100, 2)
        if current_value > cost:
            self.trade_success_count += 1
            win = [stock, percent]
            self.statis['win'].append(win)
        else:
            loss = [stock, percent]
            self.statis['loss'].append(loss)
        
    def report(self, context):
        cash = context.portfolio.cash
        totol_value = context.portfolio.portfolio_value
        position = 1 - cash/totol_value
        log.info("收盘后持仓概况:%s" % str(list(context.portfolio.positions)))
        log.info("仓位概况:%.2f" % position)
        self.print_win_rate(context.current_dt.strftime("%Y-%m-%d"), context.current_dt.strftime("%Y-%m-%d"), context)

    # 打印胜率
    def print_win_rate(self, current_date, print_date, context):
        if str(current_date) == str(print_date):
            win_rate = 0
            if 0 < self.trade_total_count and 0 < self.trade_success_count:
                win_rate = round(self.trade_success_count / float(self.trade_total_count), 3)

            most_win = self.statis_most_win_percent()
            most_loss = self.statis_most_loss_percent()
            starting_cash = context.portfolio.starting_cash
            total_profit = self.statis_total_profit(context)
            if len(most_win)==0 or len(most_loss)==0:
                return

            print "-"
            print '------------绩效报表------------'
            print '交易次数: {0}, 盈利次数: {1}, 胜率: {2}'.format(self.trade_total_count, self.trade_success_count, str(win_rate * 100) + str('%'))
            print '单次盈利最高: {0}, 盈利比例: {1}%'.format(most_win['stock'], most_win['value'])
            print '单次亏损最高: {0}, 亏损比例: {1}%'.format(most_loss['stock'], most_loss['value'])
            print '总资产: {0}, 本金: {1}, 盈利: {2}, 盈亏比率:{3}%'.format(starting_cash + total_profit, starting_cash, total_profit, total_profit / starting_cash * 100)
            print '--------------------------------'
            print "-"

    # 统计单次盈利最高的股票
    def statis_most_win_percent(self):
        result = {}
        for statis in self.statis['win']:
            if {} == result:
                result['stock'] = statis[0]
                result['value'] = statis[1]
            else:
                if statis[1] > result['value']:
                    result['stock'] = statis[0]
                    result['value'] = statis[1]

        return result

    # 统计单次亏损最高的股票
    def statis_most_loss_percent(self):
        result = {}
        for statis in self.statis['loss']:
            if {} == result:
                result['stock'] = statis[0]
                result['value'] = statis[1]
            else:
                if statis[1] < result['value']:
                    result['stock'] = statis[0]
                    result['value'] = statis[1]

        return result

    # 统计总盈利金额    
    def statis_total_profit(self, context):
        return context.portfolio.portfolio_value - context.portfolio.starting_cash
使用方法:

import tradestat

g.trade_stat = tradestat.trade_stat()
g.trade_stat.watch(context, stock)
g.trade_stat.report(context)

全部回复

0/140

量化课程

    移动端课程