前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >长期活跃于期货市场的Aberration

长期活跃于期货市场的Aberration

作者头像
数据科学实战
发布2020-05-07 17:05:37
2.3K0
发布2020-05-07 17:05:37
举报
文章被收录于专栏:数据科学实战数据科学实战
本文源自:濮元恺的《量化投资技术分析实战:解码股票与期货交易模型》(电子工业出版社)中《长期活跃于期货市场的Aberration》一文。

领取本文py源代码方式(任选其一)

1.加入VIP

2.转发本文至朋友圈,扫描文末二维码添加小黎为好友发送截图

3.转发本文至朋友圈,将截图发送至本公众号后台

Aberration可以被翻译为“失常、离开正路、越轨”等含义,是一套古老而简单的趋势类突破系统,在众多交易者看来它已经失去盈利空间,但实际上它可以用最简单的方式反馈市场波动,且经过改进之后依然可以作为极好的入门模型。如图3-6所示。

这个曾经创下100%以上年收益率的交易系统由KeithFitschen于1986年发明。1993年发布在美国FutureTruth杂志上,自策略发布之日起,其绩效一直排名靠前,而其框架实际上就是布林带系统的突破式应用,并且不是中高频交易系统,而是中低频中长线持仓的一套模型。对于这样的模型,我们拥有较多的IT平台来支持(意味着不需要在复杂的IT交易系统上做过多开发),以获取市场最原始朴素的动量效应,将其转化成我们的账户利润。

既然是基于布林带的突破模型,则一定是一个低胜率的模型,而且它又能赚钱,那么就一定是一个高盈亏比的模型,以此来对冲低胜率带来的反复亏损。Aberration的核心构成是一条均线,加上、下两个轨道,轨道宽度,是N倍标准差。用代码表达如下:

代码语言:javascript
复制
from tqsdk.tafunc import ma
def BOLL(df, n1, n2, p):
    new_df = pd.DataFrame()
    mid = ma(df["close"], n1)
    std = df["close"].rolling(n2).std()
    new_df["mid"] = mid
    new_df["top"] = mid + p * std
    new_df["bottom"] = mid - p * std
    return new_df

# 使用BOLL指标计算中轨、上轨和下轨,其中80为周期N,20为参数p1, 2为参数p2
def boll_line(klines):
    boll = BOLL(klines, 80, 20, 2)
    midline = boll["mid"].iloc[-1]
    topline = boll["top"].iloc[-1]
    bottomline = boll["bottom"].iloc[-1]
    print("策略运行,中轨:%.2f,上轨为:%.2f,下轨为:%.2f" % (midline, topline, bottomline))
    return midline, topline, bottomline

Aberration的交易规则是:当价格突破上轨时做多,当价格回到中轨时平仓;反之,当价格突破下轨时做空,当价格回到中轨时平仓。

通过Aberration系统原理窥探价格概率

1

为什么使用趋势突破类模型后可以获得收益,但是只能获得一个较低的胜率。核心原因是因为价格收益率的波动情况是类似于正态分布的,或者说是在正态分布的基础上的,偏峰肥尾。如图3-7所示。为了进一步说明偏峰肥尾,这里要引入“概率密度函数PDF(ProbabilityDensityFunction)”的概念,其可以查阅到的定义很简明:描述随机变量的输出值,在某个确定的取值点附近的可能性的函数。PDF的函数值的高低,描述数据在某个区域分布的高低。

刚才所说的偏峰肥尾需要两个附加的概念来解释,即峰度偏度,具体如下:

(1)峰度(Kurtosis)又称峰态系数。表征概率密度分布曲线在平均值处峰值高低的特征数。直观看,峰度反映了峰部的尖度。样本的峰度是和正态分布相比较而言统计量,如果峰度大于3,则峰的形状比较尖,比正态分布峰要陡峭。肥尾说明了数据的分布在概率密度函数图像上的左右两侧较远的地方更多,肥尾分布大部分对应尖峰,也就是峰态系数较高。

(2)偏峰意味着这个山峰不仅是高耸的,而且是有偏向的,其均值并不等于0。偏度(Skewness)也称为偏态、偏态系数,是统计数据分布偏斜方向和程度的度量,这个概念用来表征概率分布密度曲线相对于平均值不对称程度的特征数。正态分布的偏度为0,两侧尾部长度对称。

对峰度和偏度的描述,用正态分布最容易理解:比如正态分布,在μ处数据分布最多(我们描述为概率密度值越高),所以函数值最高。在左右两侧,概率密度值降低,说明数据点分布变得稀少。这个函数图像上,f(x)是指随机变量X(大写X,变量集合)在观察值为x(小写x,某个数值)时的概率密度值,而不是概率值。PDF函数曲线与X轴所围成的面积表示概率,该面积等于1,因为随机变量的所有可能取值(即100%)都在X轴上。μ是变量X的均值,如果是标准正态分布,则μ=0。对于服从正态分布的变量,其观测值如下。如图3-8所示。

落在距均值的距离(xi-μ),为1倍标准差范围内的概率为0.68。

◎落在距均值的距离(xi-μ),为2倍标准差范围内的概率为0.95。

◎落在距均值的距离(xi-μ),为3倍标准差范围内的概率为0.9973。

但是价格收益率分布和正态分布略有不同,以中证500指数为例,历史每日涨跌幅(百分比)分布情况,左侧明显肥尾,整体峰度偏向右侧。偏峰意味着,其价格的总体趋势还是向上运行的,也就是说多年来积累的上涨因素更多,或者说在你的考察区间内,大部分情况价格有上涨(右偏)或者下跌(左偏),是有方向性的。而大部分价格收益率的波动,集中在一个较小的区域,比如正负0.02范围内,期货领域的螺纹钢指数合约,则集中在0.01范围内(波动率比股票指数低,因为自带10倍杠杆),所以峰度总体上是较高的。

关于尾部的肥尾特性,为了弥补峰部较低的离散程度(较高的集中程度),尾部的数值需要多一些,来拉高整体的离散程度,以使其与正态分布相等。若一个分布是尖峰(均值附近的样本数比正态分布的多),则必然尾部比正态的厚(远离均值的样本数比正态分布的多)。肥尾意味着价格出现极端行情发生的机率增加,可能因为发生了一些不寻常的事件造成了市场震荡,且交易者经常过度反应市场信息,加之由于信息不对称而滞后的入场者也做同样方向的交易,叠加了价格向单一方向的运行强度(时间和空间),因此我们的趋势交易在这些时间点上有利可图。

所以通过Aberration系统,我们常用布林带设置上下轨=2倍标准差,然后做突破交易,其数学含义为:当前价格值与均值的距离,突破2倍标准差(之前统计量只有5%的数据是这样分布的),即做趋势追踪交易。虽然这样做胜率较低,但是价格显然是肥尾分布的,价格波动不回复(形成趋势)的概率比正态分布更大,且任意一次肥尾,都能够带来较大的利润。

Aberration系统交易逻辑解读

2

如果价格没有趋势,而做高度回复性的运动(比如在0轴上下反复运动,典型特征是白噪声),或者价格在一个区间内反复震荡,没有形成有效的向上或向下突破,那么此时应该使用布林带回复性交易规则,也就是在价格突破上轨后做空,在价格突破下轨后做多。如图3-9所示。

显然大部分股票价格、股票指数价格、商品期货价格都是呈现趋势性运动的,比如2014—2015年的A股大牛市,再比如商品期货焦炭从2016年供给侧改革以来的两轮上涨等,都是方向性显著的运动。此时如果继续使用布林带回复性交易规则,则会因为价格的肥尾效应带来较大亏损。

所以对于这些运动,应该有效地进行趋势追踪,特别是中长线趋势追踪。Aberration交易系统的特点是被动地趋势跟随,采用长期信号,如果运行在日频K线续航,其在一个品种上每年交易3~4次,持有时间超过总交易时间的60%,并且可以根据不同的资金规模,分配不同的品种数目。它通过长线交易捕捉趋势来获取巨额利润,同时交易在多个不相关的市场,当某一品种回撤时,另一品种可能获利。它本质上倾向于波动率出现机会对冲,所以要求必须配置多品种,这样才有更大把握在更多品种上盈利,否则系统发生年度亏损将是很正常的情况。如图3-10所示。

Aberration系统如果配置得当,可以在农产品谷物、油脂类、有色金属、工业材料、能源化工、外汇、股指期货等各类品种之间灵活运转,通过长线地追踪趋势来获得盈利。

但是在具体的交易指令发出点位,我们不仅应该遵照原系统设计的“突破上轨时做多,突破下轨做空”,而且应该考虑,在价格突破上轨入场后,因为节假日,或者添加了其他出场逻辑,而打断了本次交易后价格依然在上轨之上时,我们是否要做多(重新入场)。

我的建议是如果是中长线趋势系统,应该坚持被打断后再寻找合适机会入场,因为放弃再次入场机会,可能会错过一次巨大的持续数月的上涨行情。如果是短线系统,交易被打断后造成出场,则可以放弃再入场,因为价格会快速再回到布林带上下轨之内,带来一次新的开仓机会。

我们继续分析该系统会发现“当价格回到中轨时平仓”,这个平仓条件并非完全合理。因为仅从原意上看,价格回到中轨意味着价格均值回复,但是从一个较高或较低的位置回到中轨的过程中,价格已经释放了动能。按照动能也在均值回复的一般常识,此时经过休息后的价格有较大概率继续上升。同时价格往往在高位或者低位 呈现出快速波动的特性,也就是到达阶段性高低点时,价格会快速反转。

此时我们需要比“当价格回到中轨时平仓”更快的速度离场,如何构建这个逻辑?其实Aberration系统、双均线系统等各类趋势追踪类系统,都没有有效的应对方案,你会发现那些被描述成“印钞机”的经典交易系统,大部分都只是提供了入场逻辑,也就是说在价格出现符合其入场标准的时候,给予买入多头或者卖出空头的开仓信号,尚未考虑出场(离场)逻辑。

Aberration系统改进

3

我们按照经验,对Aberration系统加入一个追踪止损(TrailingStop,也被称为“吊灯止损”)模块,该模块的设计逻辑是识别开仓后的最高点/最低点,然后当价格出现反向运动时,测试价格和这个最高点/最低点的运行空间,当达到一定幅度时平仓离场,该模块的离场速度,显然比价格回落到均线再离场要快很多。

我们还应该留意到,如果价格在入场后,发生了大幅度快速反向运行,此时不用考虑从开单后的最高价或者开单后的最低价的价格运行幅度,而是直接考虑最新价格和入场点的幅度(亏损程度),即可设计出一个止损逻辑:

代码语言:javascript
复制
 # 在多头情况下,空仓条件
        elif position.pos_long > 0:
            #更新持仓后记录的最高价
            if quote.last_price > myhigh:
                myhigh = quote.last_price
                print('最高价更新:',myhigh)
            # 如果最新价低于中线,多头清仓离场
            if quote.last_price < midline:
                print("最新价低于中线,多头清仓离场")
                target_pos.set_target_volume(0)
            #硬止损
            elif quote.last_price < position.open_price_long - NATRstop * atr:
                print('多头硬止损')
                target_pos.set_target_volume(0)
            #跟踪止损
            elif myhigh - position.open_price_long > NATRstop * atr:
                if myhigh - quote.last_price >= NATRstop * atr:
                    print("跟踪止损,多头清仓离场")
                    target_pos.set_target_volume(0)
                    is_stop = True
            else:
                print("当前多仓,未穿越中线,仓位无变化")

        # 在空头情况下,空仓条件
        elif position.pos_short > 0:
            #更新持仓后记录的最低价
            if quote.last_price < mylow:
                mylow = quote.last_price
                print('最低价更新:',mylow)
            # 如果最新价高于中线,空头清仓离场
            if quote.last_price > midline:
                print("最新价高于中线,空头清仓离场")
                target_pos.set_target_volume(0)
            #硬止损
            elif quote.last_price > position.open_price_short + NATRstop * atr:
                print('空头硬止损')
                target_pos.set_target_volume(0)
            #跟踪止损
            elif position.open_price_short - mylow > NATRstop * atr:
                if quote.last_price - mylow  >= NATRstop * atr:
                    print("跟踪止损,空头清仓离场")
                    target_pos.set_target_volume(0)
                    is_stop = True
            else:
                print("当前空仓,未穿越中线,仓位无变化")

上段代码帮助系统构建了一个辅助的出场逻辑,但较为可惜的是增加了参数NATRstop,这在一定程度上增加了系统的不稳定性,也增加了使用者的参数判断困难。NATRstop是常见于1~10的一个参数,代表TrailingStop的价格下落(上升)幅度。在商品期货中,高波动率的品种设置要偏大,低波动率品种设置要偏小。并且在多头和空头模型中,此参数设置也不能通用,因为价格的波动并非是对称的,多头模型从开仓后的最高点到目标出场点的距离一般并不是很大,而空头模型从开仓后的最低点到目标出场点的距离可能反倒更大一些,因为价格下跌经常呈现抵抗式下跌,如果我们轻易因为追踪止损离场,可能找不到更好的入场点,或者找到了更迟、更加不利于获取利润的入场点。但是无论如何,都可以看到它是和波动率紧密相关的。并且波动率是时常变化的,比如在股票市场2012—2014年,是低波动率区间,而随后的大牛市或者特别是股灾,则变成了高波动率区间。商品期货时常也经常因为价格走入了震荡区间,而波动率显著降低。所以我们应该尝试将开仓后的最高点到目标出场点的距离,设计成一个和波动率相关的变量,并且是正相关。也就是说止损比率必须是时常变化的,是波动率自适应的,所以这里要引入ATR自适应追踪止损,它将TrailingStop改进成为一个系数乘以ATR(平均真实波动)。追踪止损的引入是带有门槛的,因为如果没有门槛,该模块会和硬止损同时起效,而且当价格运行运行高度非常有限时,也没有必要进行追踪止损,所以要带上一定的最高运行幅度门槛。

通过ATR适应波动率止损

4

我们再用一点篇幅来介绍ATR这个概念。ATR可以说构建出了我们的程序化交易系统和市场波动的沟通桥梁,让系统能够感知市场波动幅度,以此方式实现大部分参数的调整,甚至是消除了大部分参数。

ATR概念由威尔德(J.WellesWilder)在1978年于NewConceptsinTechnicalTradingSystems一书中提出,它取一定时间周期内的价格波动幅度的移动平均值,它并不是主要用于研判买卖时机,也不是做什么反趋势指标,它只能感知到波动率,仅此而已。但是正是这种简单的感知方法,让ATR能够运用到各类交易系统中,它自己不发出交易信号,却可以改善其他系统的信号发出时机,成为影响系统收益率的核心因素。甚至有人做过测试,通过ATR调整出场点,入场点随机设置(RandomEntry,即入场点位和方向都是随机的),系统依然能够保持盈利,可见ATR的作用之大。

计算ATR首先要计算出TR值,也就是单个K线上的真实波动量:TR等于“最高价-最低价”和“最高价-昨收”和“昨收-最低价”,这3个值的最大值。

然后将N个周期的TR值做移动平均即可。这里如果数据量N较小,则ATR反应敏锐,但是也意味着噪声较高;如果数据量N较大,则ATR反应较慢,但是也意味着噪声低,更加稳定。所以我们处理较小样本的TR值构成ATR的时候,可以采用EXPMA指数加权移动平均法,这种方法能够一定程度上降低ATR值的波动。不过用等权的移动平均依然是更加稳妥的方案。ATR系统自己的参数N一般不倾向于反复优化,设定为一个固定的值即可。

利用ATR设定止损和追踪止损很简单,其逻辑是选择一个基准价位,然后减去一个系数调整后的ATR值。ATR值会根据投资品种的波动率自动调整实际的百分比止损值,这就比固定使用百分比值作为止损更具灵活性了。

用ATR止损和用固定价格跳数止损都有道理,ATR评估了最近的波动率,而固定跳数是将止损量和金额紧密挂钩,ATR止损和固定价格跳数止损不好下结论哪个是最正确的,但是固定百分比止损一定是不科学的,因为价格在不同区间时,其固定百分比值代表的价格区间差异很大。

以下是部分ATR适应波动率止损模块的测试数据,如图3-11~图3-14所示。

因为一手橡胶的价值远高于一手螺纹钢,所以这类高价值品种在止损时,需要的ATR比率较小,橡胶的测试是从0.5倍ATR值开始到4倍ATR值结束。

因为已经添加了追踪止损,所以硬止损是非必需的,而且追踪止损同样代表了价格从入场后的最高点最高点回落到目标点位,它已经包含了硬止损的逻辑在其中,如果两种模块同时存在,则会损伤性能,在表格里不再呈现,读者们可以实践测试得到。所以我们从这里开始,在模型中仅保留追踪止损模块。

尝试改进波动率的描述

5

有些波动率指标会随时间变化而发生剧烈变动,而另一些则相对较为平稳;有些波动率指标的计算包含了过去时间窗口的所有数据点,而另一些则只包含了一些极端的点。我们研究中还发现,有的指标数据信息提取不足,适合通用的统计领域,但在金融市场上还有改造空间。如图3-15所示。

图3-15ATR和SD(标准差)在面对波动率不变,仅方向变化的情况下,标准差发生指示偏差。

传统的Aberration系统采用标准差作为波动率描述工具,所以价格突破的上下轨宽度为N倍标准差,实际上很多交易者熟知的ATR指标也有很强的波动率描述能力,甚至比标准差更好,它使用了历史最高最低价,和收盘价,而标准差仅使用了收盘价。所以ATR的信息含量较大。

从我们的测试结果来看,两者皆可作为系统中的波动率指示工具。商品期货上两者性能差异不明显,但是到了股指方面,ATR的优势进一步显现。这其中最核心的因素恰巧是交易次数,带来的绩效IR(绩效IR=绩效×sqrt(交易次数,或者说信号数量))提升,这里我们定义的IR和信息广度有关,我们认为信号数量是对于绩效可信度的考察方式。

其实Aberration系统或者说布林带还隐藏了一个更容易影响性能的细节,远比选择ATR作为替换工具更重要,那就是标准差的计算周期length参数。在日线周期上,由于我们惯用20或者40周期,所以均线的length参数和标准差的length参数可以统一。如图3-16所示。

但是到了小时线上,我们需要注意均线length参数可能需要80~100周期,而标准差length参数如果依然设置80~100周期,则无法及时反馈近期波动(可以想象当新的数据点加入到模型时,即使它是一个剧烈的波动,也因为权重过小无法及时反馈当前的波动率变化)。所以建议给予标准差独立的length参数。我们建议设置为5天~10天的窗口期(如某期货品种每天有4个小时线,则5天有20个样个样本)作为标准差length参数,Aberration系统中轨的均值参数则可以设置略大一些。

认为布林带仅有两个参数,是大多数交易者容易忽略的问题,所以提示读者们如果在较细致的时间周期上,标准差的周期一定不能设置过大,依然是以20~40周期为宜。

至此,我们对于Aberration系统的迭代暂时告一段落,比较遗憾的是我们没有修改Aberration系统主逻辑,特别是入场逻辑,而是以出场为核心改进点,同时做了一些低风险加仓动作。需要说明的是,这应该是一个程序化交易者在1年内应该达到的开发水平,如果你的时间有限,进步速度较慢,也一定要尽快达到此门槛,因为这样的系统才勉强能够用于实盘交易。当然它比起大部分手工交易者的绩效仍然好太多了,这就是我们为什么要做量化的一个实际表现。

如图3-17所示是我们将Aberration系统加载在28个主要期货品种上的测试结果,模型将length参数固定为80,标准差倍数固定为1,仅留下一个参数——ATR追踪止损系数,可供各品种调整,这样保证了模型尽可能低程度地拟合历史数据,让绩效得到真实性保证。

在商品期货测试中,分配给每个品种20000元等额资金,交易手续费5%%(万分之5,显著高于市场平均手续费5倍以上),滑点开平仓各1跳,得到如图3-18所示的绩效。测试全程夏普比率1.46,收益风险比1.55,胜率39.86%。

基于tqsdk(天勤)编译的Aberration交易系统回测代码:

代码语言:javascript
复制
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = "Ringo"

'''
Aberration策略 (难度:初级)
参考: https://www.shinnytech.com/blog/aberration/
注: 该示例策略仅用于功能示范, 实盘时请根据自己的策略/经验进行修改
'''

from tqsdk import TqApi, TargetPosTask,TqBacktest,TqSim
from tqsdk.tafunc import ma
from tqsdk.ta import ATR
import pandas as pd
from datetime import date

# 设置合约代码
SYMBOL = "SHFE.rb2010"
NATRstop = 2 #N倍ATR止损
api = TqApi(account=TqSim(init_balance=50000),backtest=TqBacktest(start_dt=date(2020, 1, 1), end_dt=date(2020, 4, 21)))
quote = api.get_quote(SYMBOL)
klines = api.get_kline_serial(SYMBOL, 60 * 60)
position = api.get_position(SYMBOL)
target_pos = TargetPosTask(api, SYMBOL)
        
def BOLL(df, n1, n2, p):
    new_df = pd.DataFrame()
    mid = ma(df["close"], n1)
    std = df["close"].rolling(n2).std()
    new_df["mid"] = mid
    new_df["top"] = mid + p * std
    new_df["bottom"] = mid - p * std
    return new_df

# 使用BOLL指标计算中轨、上轨和下轨,其中80为周期N,20为参数p1, 2为参数p2
def boll_line(klines):
    boll = BOLL(klines, 100, 40, 2)
    midline = boll["mid"].iloc[-1]
    topline = boll["top"].iloc[-1]
    bottomline = boll["bottom"].iloc[-1]
    print("策略运行,中轨:%.2f,上轨为:%.2f,下轨为:%.2f" % (midline, topline, bottomline))
    return midline, topline, bottomline

counter = 0 #计数器
is_stop = False #止损标识符
midline, topline, bottomline = boll_line(klines.iloc[:-1])
Highest_high_2_20 = sorted(klines.iloc[-21:-1].high,reverse=True)[1]
Lowest_low_20 = sorted(klines.iloc[-21:-1].low,reverse=False)[1]
atr = ATR(klines,14).iloc[-1].atr

while True:
    api.wait_update()
    # 每次生成新的K线时重新计算BOLL指标
    if api.is_changing(klines.iloc[-1], "datetime"):
        midline, topline, bottomline = boll_line(klines.iloc[:-1])
        Highest_high_2_20 = sorted(klines.iloc[-21:-1].high,reverse=True)[1]
        Lowest_low_20 = sorted(klines.iloc[-21:-1].low,reverse=False)[1]
        atr = ATR(klines,14).iloc[-1].atr
        print('20周期高点:',Highest_high_2_20,'20周期低点:',Lowest_low_20,'atr:',atr)
        #计数器控制循环,止损后30根K线内不开仓,30根后止损标识符复位
        if is_stop:
            counter += 1
        if counter > 30:
            is_stop = False
            counter = 0

    # 每次最新价发生变化时进行判断
    if api.is_changing(quote, "last_price"):
        # 判断开仓条件
        if position.pos_long == 0 and position.pos_short == 0:
            # 如果最新价大于上轨,K线上穿上轨,开多仓
            if quote.last_price > topline and is_stop == False and quote.last_price >= Highest_high_2_20:
                print("K线上穿上轨,开多仓")
                target_pos.set_target_volume(1)
                myhigh = quote.last_price #记录开仓后的最高价用于跟踪止损
            # 如果最新价小于轨,K线下穿下轨,开空仓
            elif quote.last_price < bottomline and is_stop == False and quote.last_price <= Lowest_low_20:
                print("K线下穿下轨,开空仓")
                target_pos.set_target_volume(-1)
                mylow = quote.last_price #记录开仓后的最低价用于跟踪止损
            else:
                print("当前最新价%.2f,未穿上轨或下轨,不开仓" % quote.last_price)

        # 在多头情况下,空仓条件
        elif position.pos_long > 0:
            #更新持仓后记录的最高价
            if quote.last_price > myhigh:
                myhigh = quote.last_price
                print('最高价更新:',myhigh)
            # 如果最新价低于中线,多头清仓离场
            if quote.last_price < midline:
                print("最新价低于中线,多头清仓离场")
                target_pos.set_target_volume(0)
            #硬止损
            elif quote.last_price < position.open_price_long - NATRstop * atr:
                print('多头硬止损')
                target_pos.set_target_volume(0)
            #跟踪止损
            elif myhigh - position.open_price_long > NATRstop * atr:
                if myhigh - quote.last_price >= NATRstop * atr:
                    print("跟踪止损,多头清仓离场")
                    target_pos.set_target_volume(0)
                    is_stop = True
            else:
                print("当前多仓,未穿越中线,仓位无变化")

        # 在空头情况下,空仓条件
        elif position.pos_short > 0:
            #更新持仓后记录的最低价
            if quote.last_price < mylow:
                mylow = quote.last_price
                print('最低价更新:',mylow)
            # 如果最新价高于中线,空头清仓离场
            if quote.last_price > midline:
                print("最新价高于中线,空头清仓离场")
                target_pos.set_target_volume(0)
            #硬止损
            elif quote.last_price > position.open_price_short + NATRstop * atr:
                print('空头硬止损')
                target_pos.set_target_volume(0)
            #跟踪止损
            elif position.open_price_short - mylow > NATRstop * atr:
                if quote.last_price - mylow  >= NATRstop * atr:
                    print("跟踪止损,空头清仓离场")
                    target_pos.set_target_volume(0)
                    is_stop = True
            else:
                print("当前空仓,未穿越中线,仓位无变化")
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据科学实战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档