V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
mushroomqiu
V2EX  ›  Python

福利到!用 Python 实现海龟交易系统

  •  
  •   mushroomqiu · 2016-09-05 14:43:21 +08:00 · 3028 次点击
    这是一个创建于 3002 天前的主题,其中的信息可能已经有所发展或是发生改变。
    前言

    海龟交易系统本质上是一个趋势跟随的系统,但是最值得我们学习的,是资金管理尤其是分批建仓及动态止损的部分

    一、趋势捕捉

    唐奇安通道

    该指标是有 Richard Donchian 发明的,是有 3 条不同颜色的曲线组成的,该指标用周期(一般都是 20 )内的最高价和最低价来显示市场价格的波动性,当其通道窄时表示市场波动较小,反之通道宽则表示市场波动比较大。 如图所示:
    该具体分析为:
    当价格冲冲破上轨是就是可能的买的信号;反之,冲破下轨时就是可能的卖的信号。
    该指标的计算方法为:

    上线=Max (最高低, n )
    下线=Min (最低价, n )
    中线=(上线+下线)/2
    高清源代码请移步: https://uqer.io/community/share/57bd5864228e5b79a575a9b2
    海龟交易就是利用唐奇安通道的价格突破来捕捉趋势。
    不过我们在向下突破 10 日唐奇安下沿卖出。
    二、资金管理

    2.1 、 N 值计算

    N 值是仓位管理的核心,涉及加仓及止损。另外, N 值与技术指标平均真实波幅 ATR 很相似
    首先介绍真实波幅: 真实波幅是以下三个值中的最大值
    1 、当前交易日最高价和最低价的波幅
    2 、前一交易日的收盘价与当前交易日最高价的波幅
    3 、前一交易日的收盘价与当前交易日最低价的波幅
    用公式写就是:
    TrueRange=Max(High−Low,High−PreClose,PreClose−Low)
    接下来, N 值计算公式为:
    N=PreN[−19 :]+TrueRange20
    其中 preN 为前面 N 值, TrueRange 为当前的真实波幅,此公式的真是含义为计算之前 20 天(包括今天在内)的 N 的平均值
    另外,有些海龟交易系统用的是 ATR 来代替 N 值, ATR 为真实波幅的 20 日平均。
    2.2 买卖单位及首次建仓
    先给出公式:
    Unit=1%∗Account/N
    首次建仓的时候,当捕捉到趋势,即价格突破唐奇安上轨时,买入 1 个 unit 。
    其意义就是,让一个 N 值的波动与你总资金 1%的波动对应,如果买入 1unit 单位的资产,当天震幅使得总资产的变化不超过 1%。例如:
    现在你有 10 万元资金, 1%波动就是 1000 元。假如标 X 的 N 值为 0.2 元, 1000 元÷0.2 元=5000 股。也就是说,你的第一笔仓位应该是在其突破上轨(假设为 5 元)时立刻买入 5000 股,耗资 25000 元。
    2.3 加仓

    若股价在上一次买入(或加仓)的基础上上涨了 0.5N ,则加仓一个 Unit 。
    接上面的例子:假如 N 值仍为 0.2 。
    价格来到 5 + 0.2*0.5 = 5.1 时,加仓 1 个 Unit ,买入 5000 股,耗资 25500 元,剩余资金 49500 元
    价格来到 5.1 + 0.2*0.5 = 5.2 时再加仓 1 个 unit 。买入 5000 股,耗资 26000 元,剩余资金 23500 元
    2.4 动态止损

    当价格比最后一次买入价格下跌 2N 时,则卖出全部头寸止损。
    接上面的例子,最后一次加仓价格为 5.2 。假如此时 N 值 0.2 元。 当价格下跌到 5.2 - 2*0.2 = 4.8 元时,清仓。
    持仓成本为 ( 5+5.1+5.2 )*5000/15000 = 5.1 元。 此时亏损 ( 5.1-4.8 )*15000 = 4500 元 对于 10 万来说 这波亏损 4.5%
    2.5 止盈

    当股价跌破 10 日唐奇安通道下沿,清空头寸结束本次交易
    三、代码实现

    本代码用 ATR 代替 N 值进行计算,其他逻辑不变:
    ATR=MA(TrueRange,20)
    我们以单只股票为标,建立海龟交易系统,当然,可以将总资产均分为 n 份,同时交易 n 个标。

    计算 ATR 值用日线数据,监控价格突破采用分钟线
    0 初始化参数,在 initialize(account)写入
    def initialize(account):
    account.last_buy_prcie = 0 #上一次买入价
    account.hold_flag = False # 是否持有头寸标志
    account.limit_unit = 4 # 限制最多买入的单元数
    account.unit = 0 # 现在买入 1 单元的股数
    1 唐奇安通道计算及判断入场离场:

    我们设计个函数,传入值为回测中 account.get_history()取得的某单个股票的历史数据、股票现价、 T 为计算唐奇安通道的数据长度,转化为 dataframe 格式
    def IN_OR_OUT(data,price,T):
    up = max(data['highPrice'].iloc[-T:])
    down = min(data['lowPrice'].iloc[-int(T/2):]) # 这里是 10 日唐奇安下沿
    if price>up:
    return 1
    elif price<down:
    return -1
    else:
    return 0
    2. ATR 值计算:


    1
    def CalcATR(data):
    2
    TR_List = []
    3
    for i in range(1,21):
    4
    TR = max(data['highPrice'].iloc[i]-data['lowPrice'].iloc[i],data['highPrice'].iloc[i]-data['closePrice'].iloc[i-1],data['closePrice'].iloc[i-1]-data['lowPrice'].iloc[i])
    5
    TR_List.append(TR)
    6
    ATR = np.array(TR_List).mean()
    7
    return ATR
    3. 计算 unit,注意股数为 100 的整数倍


    1
    def CalcUnit(perValue,ATR):
    2
    return int((perValue/ATR)/100)*100
    查看全部
    4.判断是否加仓或止损:

    当价格相对上个买入价上涨 0.5ATR 时,再买入一个 unit
    当价格相对上个买入价下跌 2ATR 时,清仓

    1
    def Add_OR_Stop(price,lastprice,ATR):
    2
    if price >= lastprice + 0.5*ATR:
    3
    return 1
    4
    elif price <= lastprice - 2*ATR:
    5
    return -1
    6
    else:
    7
    return 0
    查看全部
    5 判断上次卖出操作是否成功(可能出现当日买进,之后却判断需要卖出)


    1
    def SellComplete(hold_flag,security_position):
    2
    if len(security_position)>0 and hold_flag==False:
    3
    return True
    4
    else:
    5
    return False
    查看全部
    构建策略

    分钟线回测时间略长啊~
    先把上面写的函数集中下,方便微核充启后运行函数

    1
    ################################################### 计算、判断函数 #####################################################################
    2
    def IN_OR_OUT(data,price,T):
    3
    up = max(data['highPrice'].iloc[-T:])
    4
    down = min(data['lowPrice'].iloc[-int(T/2):]) # 这里是 10 日唐奇安下沿
    5
    if price>up:
    6
    return 1
    7
    elif price<down:
    8
    return -1
    9
    else:
    10
    return 0
    11

    12
    def CalcATR(data):
    13
    TR_List = []
    14
    for i in range(1,21):
    15
    TR = max(data['highPrice'].iloc[i]-data['lowPrice'].iloc[i],data['highPrice'].iloc[i]-data['closePrice'].iloc[i-1],data['closePrice'].iloc[i-1]-data['lowPrice'].iloc[i])
    16
    TR_List.append(TR)
    17
    ATR = np.array(TR_List).mean()
    18
    return ATR
    19

    20
    def CalcUnit(perValue,ATR):
    21
    return int((perValue/ATR)/100)*100
    22

    23
    def Add_OR_Stop(price,lastprice,ATR):
    24
    if price >= lastprice + 0.5*ATR:
    25
    return 1
    26
    elif price <= lastprice - 2*ATR:
    27
    return -1
    28
    else:
    29
    return 0
    30

    31
    def SellComplete(hold_flag,security_position):
    32
    if len(security_position)>0 and hold_flag==False:
    33
    return True
    34
    else:
    35
    return False
    查看全部

    1
    import numpy as np
    2
    import pandas as pd
    3
    from __future__ import division
    4
    from CAL.PyCAL import *
    5
    import matplotlib.pyplot as plt
    6

    7
    start = '2012-01-01' # 回测起始时间
    8
    end = '2016-01-01' # 回测结束时间
    9
    benchmark = '000001.XSHE'
    10
    universe = ['000001.XSHE']
    11
    capital_base = 100000 # 起始资金
    12
    freq = 'm' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测
    13
    refresh_rate = 1 # 调仓频率,表示执行 handle_data 的时间间隔,若 freq = 'd'时间间隔的单位为交易日,若 freq = 'm'时间间隔为分钟
    14

    15

    16
    #----------------------------------- 记录部分数据 -----------------------------
    17
    global record
    18
    record = {'break_up':{},'break_down':{},'stop_loss':{},'position':{},'ATR':{}} # 记录入场、离常、止损点、持仓比、 ATR
    19
    #---------------------------------------------------------------------------------------
    20

    21
    高清源代码请移步: https://uqer.io/community/share/57bd5864228e5b79a575a9b2
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2968 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 00:16 · PVG 08:16 · LAX 16:16 · JFK 19:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.