资源加载中... loading...

Python商品期货量化入门教程

Author: 雨幕(youquant), Created: 2024-09-12 09:11:33, Updated: 2024-09-12 09:17:23

”和“未来预期”一样稳定可靠,否则绝不投资。量化交易回测就像是后视镜,如何通过回测判断策略预期,就得使用科学的回测方法。

9.4.1 样本内和样本外回测

期货交易往往当时很难理解,但事后分析起来很简单,那是因为复盘总是站在上帝视角。量化交易回测也同样存在这个问题,回测是站在数据的终点往数据的起点看,那么企图在有限的数据中发现规律,无异于坐井观天。

为了解决这个问题,通常是把数据分成样本内数据和样本外数据。样本内数据相当于上课学习的课本知识,样本外数据相当于课后作业和期末考试。而量化交易中是在样本内数据上进行策略参数调优,在样本外数据上验证策略是否有效。

数据的划分并没有严格的要求,但至少有几个原则:在数据有限的情况下,通常样本内与样本外的比例是:6:4 或者 7:3;如果数据足够,则这比例可以更宽限一些,可以分为:5:5 甚至 2:8;尤其是逻辑简单的日内短线策略,可以减少样本内数据,更多的分配给样本外数据。

9.4.2 样本递进回测

但是仅凭一次测试就判定策略的好坏显然是不太合理的,因为回测的结果也有运气的成分,有可能保留了不好的策略,也有可能把好的策略筛选掉。那么样本递进回测将是一种更好的回测方式。

样本递进回测是将数据分为多个阶段,每个阶段又分为样本内数据和样本外数据,通过对样本内数据优化得到策略参数,再应用到样本外进行检验,并且不断以递进方式移动样本段,最后将所有样本外的测试报告组合成一个整体的回测绩效报告。

注意:在实际应用中,可以通过改变测试数据的长度,进行多次测试,用来判断策略在应对非平稳数据的稳定性。

9.4.3 样本交叉回测

除了递进回测外,还有一种交叉回测方式。这也是一种动态的回测方式,将数据分为多个阶段,每个阶段又分为样本内数据和样本外数据,通过对样本内数据优化得到策略参数,再应用到样本外进行检验,只不过交叉回测的样本外数据是贯穿整个样本,最后将所有样本外的测试报告组合成一个整体的回测绩效报告。

交叉回测最大的优点就是充分的利用有限的数据,每个样本内数据同样也是样本外数据。但交叉回测应用时也存在明显的缺点:

  1. 当价格数据非平稳时,模型的测试结果往往不可靠。例如,用 2008 年的数据做样本内,用 2005 年的数据做样本外。很有可能 2008 年的市场环境与 2005 年相比发生了很大变化,所以策略测试的结果不可信。

  2. 与第一条类似,在交叉回测中,如果用最新的数据作为样本内优化策略,而用较老的数据回测策略,这本身就不符合逻辑。

优秀的交易策略应该能够在未来具有获利性,很多时候直接在全部的历史数据上选择最优参数是非常危险的,如果先利用样本内数据进行参数优化,再利用样本外数据进行样本外测试,除了能客观检测交易策略外,更能效率节省时间。

量化交易策略本质上就是一个从大量的貌似随机的数据中找寻局部非随机数据的过程,如果不借助统计学的知识,很容易数据陷阱中。如果发现样本外数据表现不好,又觉得丢掉策略太可惜或者不愿意承认这个策略不行,而对着样本外数据继续做优化,直到样本外数据上也表现得一样好,那最后受伤的一定是自己的真金白银。

但即便拥有庞大数据的历史,但面对浩瀚无尽且不可预测的未来,历史就显得极度匮乏。所以基于历史自下而上倒推出来的交易系统,终究会随着时间而沉没。因为历史不能穷尽未来。因此一个完整的正期望交易系统必须由其内在原理或逻辑所支撑。

第10章 风险管理与投资组合

量化交易最关键的常识就是风险,但对于大多数交易者来说,风险是一个令人不愉快的话题。虽然严格控制风险意味着与暴利绝缘,但对于优秀的量化交易者来说资金和风险管理绝对有必要。

10.1 认识期货中的风险

大部分初学者热衷于谈交易技术,这个无可厚非。因为技术是基础的东西,初入市场的人最直观可以学到的。技术就像你在撸代码中使用的编程语言、或者库、或者框架,合理使用技术会初步积累你在市场中的优势。但资金管理也同样重要。

10.1.1 系统性风险

在量化交易中,系统性风险是指与整个市场相关的风险,无法通过个体交易行为控制或规避的风险因素。这包括宏观经济因素、全球金融市场的波动、政治事件等。例如,金融危机或全球经济衰退会导致市场整体下跌,从而影响到所有交易者的投资组合。对于量化交易者来说,面对系统性风险,最常见的风险管理方法是通过多样化投资组合,利用相关性较低的资产进行对冲,以降低整体风险暴露。

10.1.2 人为主观风险

人为主观风险在量化交易中同样存在,尽管交易决策主要依赖于算法和模型,但交易者的主观情绪和行为仍然可能影响交易结果。例如,情绪化的交易决策、过度自信导致的过度交易以及缺乏纪律性的行为可能会使交易者偏离原定的策略,从而增加亏损的风险。为了应对人为主观风险,量化交易者通常会通过建立严格的交易规则和纪律,以及采用自动化执行交易的方式来减少情绪干扰,确保交易的客观性和一致性。

10.1.3 策略风险

在量化交易中,策略风险指的是与交易策略本身相关的风险,包括模型不准确、参数选择不当、市场条件变化等因素。即使是经过充分测试和优化的交易策略,也可能在实际交易中遇到亏损。为了降低策略风险,量化交易者通常会采取多种策略多样化投资的方式,以及建立有效的风险管理措施。这可能包括对策略进行定期检查和优化,灵活地调整参数和模型,以适应不断变化的市场条件,从而降低策略风险并提高投资组合的稳定性。

10.1.4 资金管理的意义

就如上面所述,期货市场的风险规模大,涉及面广,具有放大性、复杂性与可预防性等特征。期货的风险成因主要有价格频繁波动、保证金交易的杠杆效应、非理性投机及市场机制不健全等等。

因此,我们需要正确对待资金管理。资金管理的主要功能是控制净值回撤并提高交易稳定性,而不是单纯追求盈利。通过合理的总仓位控制亏损,可以确保交易策略能够持续执行而不至于资金耗尽。需要明确的是,资金管理并不能将一个本身是负期望的交易策略从亏损状态扭转为盈利状态。然而,它可以避免一个本身是正期望的交易策略由于不合理的资金管理而从盈利状态转变为亏损状态。因此,虽然资金管理并非万能,但它是交易系统中不可或缺的一部分。

10.1.5 资金管理的方法

第 1 种:固定百分比资金管理

固定百分比资金管理,是一种非常流行的方法,同时也比较稳健,它的优点是在回撤期,延缓本金的下降速度,而在行情来的时候,又可以加快本金的上涨速度。并且它的方法也非常简单,所以建议初学者采用这种资金管理方式, 它的计算公式如下:

$f^* = \frac{{\text{剩余本金} \times N\%}}{{\text{止损距离(点)} \times \text{每一点代表的金额}}}$

其中, N 代表策略设定最大能承受的亏损额度的百分比, 止损距离就是开仓点减去止损点。

第 2 种:赢冲输缩 赢冲输缩是一种资金管理策略,旨在通过调整交易时的头寸大小来控制风险,并延长投资者在市场中的生存时间。在期货市场中,这种策略可以通过以下方式进行应用:

赢冲(Winning Streak): 当投资者获利时,根据赢冲策略,他们会增加投资的头寸大小。例如,假设投资者开始时拥有100元,每次交易只投入总资金的10%。如果第一次交易赢了,他们会将获利后的资金中的 10% 增加于下一次交易,以此类推。这样做的目的是在盈利时增加投资规模,以获得更大的收益。

输缩(Losing Shrink): 相反,当投资者遭受亏损时,根据输缩策略,他们会减少投资的头寸大小。假设上一次交易亏损了,投资者在下一次交易中只会使用剩余资金中的 10% 作为投资,而不是总资金的 10% 。这样做的目的是在亏损时减少投资规模,以降低亏损带来的损失。

在期货市场中,赢冲输缩策略的应用可以帮助投资者更有效地管理风险。通过在盈利时增加头寸大小,在亏损时减少头寸大小,投资者可以更灵活地调整自己的交易规模,从而保护资金并延长在市场中的生存时间。这种策略的优势在于在盈利时能够加大收益的同时,通过在亏损时减少头寸大小来控制风险,从而保持资金的稳定性。

第 3 种:分散式交易

华尔街有句名言:不要把所有的鸡蛋放在同一个篮子里面。多元化资产配置,是唯一的免费午餐。单品种的稳定性和抗风险性极差。并且单个品种的市场容量是有限的,大资金出入会对市场造成很大的冲击,出入场都很难成交在理想价位。品种分散,还可以参与150多个全球市场, 从商品,黄金,到货币和股票指数等。除了品种分散,还可以多策略、多参数、多周期组合。从而达到削峰填谷的目的。

第 4 种:凯利公式

凯利公式是一个特定赌局中,使得拥有正期望值之重复行为长期增长率最大化的公式。公式如下:

f* = (bp - p) / b = (p(b+1) - 1) / b

其中:

  • f*为现有资金应进行下次投注的比例;
  • b 为投注可得的赔率( 不含本金) ;
  • p 为获胜率;
  • q 为落败率, 即 1 - p;

注意,这个公式的适用范围是反复多次下注的场景。这是一切赌戏和投资最基本的道理,也就是『没有把握,决不下注』-不下注,就不会输。暴力背后往往背负着风险,

在期货市场中,凯利公式同样可以用于确定每个交易的头寸大小,以最大化长期利润。以下是应用凯利公式在期货市场中的一般步骤:

  1. 确定期望收益率和赔率: 首先,需要对交易进行分析,确定每个交易的期望收益率和赔率。期望收益率可以通过技术分析、基本面分析或其他方法来估计,而赔率则取决于交易的结构和条件。例如,如果你期望一笔交易的收益率是10%,而止损和获利点的比例为2:1,那么赔率就是2。

  2. 计算获胜概率: 接下来,需要估计每个交易的获胜概率。这可能需要基于历史数据或者技术分析来进行。对于某些交易策略,可能需要经验或模拟交易来确定获胜概率。

  3. 应用凯利公式: 一旦确定了期望收益率、赔率和获胜概率,就可以使用凯利公式来计算每个交易的头寸大小。

  4. 确定头寸量: 最后,将计算得到的 f* 与可用资金相乘,得出每个交易的头寸量。这将确定在每个交易中应该投入的资金比例,以最大化长期利润。

需要注意的是,凯利公式提供的是一种理论上的最优投资策略,但在实际应用中,仍然需要考虑到市场条件、个人风险偏好以及其他因素。因此,投资者可能会根据自己的情况对凯利公式的计算结果进行调整。

资金管理的重要性无论怎么强调都不为过,当然不同的交易者有不同的资金管理方式,如同没有策略圣杯一样,没有一种资金管理是适合所有投资方式的,适合的才是最好的。

10.2 等价鞅资金管理

鞅是概率论中的一种随机过程,也就是说这个随机过程未来的期望值与当前时间点的值相同。在量化交易中鞅代表了收益期望为 0,如果某个策略的交易过程是鞅,那么在理想情况下其未来的净值跟当前的净值一样。

10.2.1 什么是马丁格尔

马丁格尔是一种等价鞅式的资金管理方法,英文直译为:martegal,最初是指控制马车的马具。后来马丁格尔代表一种赌博策略。最早可以追溯到十八世纪,历经几百年经久不衰,直到现在还有很多马丁格尔或者类似的策略。

马丁格尔最初应用在轮盘赌博中,逐渐延伸到金融交易中,直到现在在股票、期货、外汇,还能看到马丁格尔的影子。之所以经久不衰,是因为从理论上讲,这是一种永不亏钱的策略。

10.2.2 正向马丁格尔

这种永不亏钱的秘诀在于,在每次赔钱后,将赌注加倍,而在任何一次赢钱之后,将赌注回归到初始单位。无论在赢钱之前输了多少次,只要概率让下注者赢一次,不但能赢回之前所有的损失,还外加一次赌注的收益。马丁格尔在金融市场中,创造了很多盈利奇迹和滑铁卢的亏损。

以抛硬币为例,出现正反面的概率约等于50%,连续出现正面或反面的次数,都是以 50%的概率开始递减,也就是说在任何一次抛硬币中,出现正面的概率是 50%,连续 2 次出现正面的概率是 25%,连续 3 次出现正面的概率是 12.5%等等以此类推。

如果最开始赌注是 1 元,连续输钱的赌注以 2 的倍数增加,也就是:1、2、4、8、16、32、64、128、256、512 等等,直到赢钱为止,一个回合才结束,所以每个回合都能赢得 1 元。虽然在纸面上,马丁格尔可以做到永不亏钱,但是随着一连串的损失发生,赌注的规模会呈几何倍的速度增加。

注意:为了避免资金雄厚的赌徒运用这个策略,几乎所有的赌场对每一次赌局有最高的下注限制。

10.2.3 反向马丁格尔

与正向马丁格尔相反,反向马丁格尔则是每次赢的时候,将赌注加倍,直到出现赔钱的时候将赌注回归到初始单位。这是马丁格尔策略的延伸,理论上这种策略更适合用在趋势行情中,因为顺势而为的操作有很高的成功率。成功率的提高伴随的是逐步加仓获取的超额收益。

10.2.4 马丁格尔在期货市场上的应用

虽然在期货市场并没有最高下单量的限制,但与赌场不同的是,期货的涨跌并不是完全随机赌大小,真实的金融交易市场要比赌场更加复杂。如果将马丁格尔策略用在期货交易中,一旦市场按照反方向趋势行情运行,后面随着行情的发展,头寸翻倍增加会越来越大,风险也随之加大。那么对于想要使用马丁格尔策略用于期货市场的交易者来说,至少需要解决 3 个问题:

  • 起始仓位
  • 加仓倍数
  • 加仓距离

注意:起始仓位需要根据你的资金量而定,也就是在交易之前计算好资金能承受的最大连续亏损次数。如果起始仓位过高,会导致每次翻倍加仓后投入过大的资金量。另外加仓倍数太高也会导致同样的问题,马丁格尔默认是双倍加仓,如果设置成 3 倍加仓,破产的速度会更快,但如果设置成 1.5 倍加仓,就会出现另一种结果。最后需要考虑的是加仓的距离,比如在 5000 点开多单,价格下跌 15 点加仓,和价格下跌 30 点加仓,也是不一样的。这点完全取决于交易者的风险承受能力和交易习惯偏好。

10.3 构建投资组合和风险控制

有人曾经做过一个研究,长期来看,整个投资收益中来自择时部分的还不足 5%,剩下的约 90% 的投资收益都是来自于成功的投资组合,这个人就是“全球资产配置之父”加里·布林森。

10.3.1 投资分散与均衡

一个好的投资组合有助于家族财富的传承,在财富的更替洗牌中,那些历经百年依然屹立不倒的家族,绝非偶然。比如洛克菲勒家族、摩根家族、罗斯柴尔德家族等等。基本都是靠某个行业发家,而后代则是靠均衡的资产配置,使这些财富长期保持增长。

在量化交易中,一个好的投资组合可以在跌宕起伏的金融市场中起到“削峰填谷”的作用。均衡的资产配置就跟合理的搭配膳食一样。营养学界流传着这样一种说法:没有不好的食物,只有不合理的膳食。

但是在投资领域“资产配置”这个词一直饱受争议。有人说,不能把所有的鸡蛋放在同一个篮子里;也有人说,与其鸡蛋放在多个篮子里,不如放在一个篮子里,然后看好这个篮子。特别是中国过去十几年快速发展,导致资产价格升值过快,在房价暴涨的背景下,只需要买房,就能轻易的跑赢通货膨胀,均衡的资产配置显的可有可无。但现在不一样了,国内经济增速明显下降,资产价格持续回落,加上全球货币宽松,资产变化轮动加快。特别是在高速通胀环境下,单一的资产配置的时代已经过去。

10.3.2 投资组合分类

商品期货只是量化交易投资组合中的一部分,其中还包括:基金、债券、股票等等,从收益的角度看:基金<债券<股票<期货。从风险的角度看也是同样的顺序:基金<债券<股票<期货。这些都可以用于投资组合。

除了多品种组合外,也可以将不同的策略组合到一起,比如:CTA 趋势策略、CTA 震荡策略、跨期套利策略等等。在实际应用中,不同周期的数据也可以组合到一块,比如:15 分钟、1 小时、2 小时、日线数据组合到一块。

10.3.3 构建投资组合

通过将上述这些不完全相关的资产加入到组合中,就可以有效降低系统性风险,同时收益最大化;也可以在总体回报率不变的情况,大概率降低亏损的概率,波动(风险)最小化。

  • 鸡蛋不要放在同一个篮子里(分散)
  • 篮子也不要放在同一个地方(分散)
  • 不要一次性把鸡蛋都放进去(定投)
  • 也不要在篮子里只是放鸡蛋(多元)

并且最大程度分散风险,稳健增值。即使在不利的市场环境中,也能具备足够的防御性。另外,投资是反人性的,科学的投资组合,可以稍微顺从一些人性,提高投资的容错率。

在投资组合中,一定要先解决保障性配置,也就是保险。它是整个资产配置的前提和基础保障。另外配置低风险、低收益的货币基金,兼顾日常消费和周转资金的流动性。其次配置一些用来跑赢 GDP 的投资品种,确保整个投资组合有好的收益基础。低风险的政府债券、企业债券、债券基金、黄金、房地产等是较好的选择。

如果想要跑赢“印钞机”的速度(M2),就需要配置一些高风险、高收益的资产,比如:个股、ETF、股票型基金、混合型基金;或者风险更高的美股、港股、商品期货、外汇现货等。最后,用很少的一部分钱,去博胜率小赔率大的机会。比如:项目股权、数字货币。

10.3.4 收益与风险

投资组合没有固定的模式和比例,一切取决于自己的风险偏好、收益预期、投资期限,将资金在不同资产类别之间合理分配。从收益风险比的角度可以划分为:保守型、稳健型、激进型。

注意:如果你对风险的承受能力较弱,就需要多配置些第 1 条和第 2 条;如果你对收益要求比较高,就需要多配置第 2 条和第 3 条。

但这并非一成不变,而是因人而异,并根据资本市场行情动态调整。通常股市与债券的相关系数大约为 0.6,如果股市比较低迷,那么债券市场相对比较火爆。比如,2008 年股市低迷的时候,债券市场风生水起。

客观的讲,摆在投资者面前的工具,并不只有投资组合,还有品种选择和市场择时,但对于大多数人而言,真正有用的也就只有投资组合,而且往往还能兵不血刃,出奇制胜。总之,投资是一种极大的不确定性行为,任何风险会在任何时候,都可能一触即发,所以投资组合绝对不能缺席,因为在崩盘的时候会让你稍微好过一些,而且在最应该买入的时候,也能产生足够的现金。

第11章 交易技巧及交易理念

华罗庚在谈到读书方法的时候,提到“读书是由薄到厚再由厚到薄的过程”。交易也类似,刚开始什么都不懂自然就很“薄”,等到入门发现需要学习内容太多就感到很“厚”,随着日积月累,理解了交易的核心,升华到交易理念时就变的很“薄”。

11.1 止盈止损

交易界有句古老的谚语:“会买是徒弟,会卖是师傅”。顾名思义怎么卖比怎么买更难,因为在买入的时候只需要判断行情是否开始就可以了;但是一旦买进之后,不但需要判断行情是否转向,还需要时刻控制风险。相信很多交易者都经历过过山车的行情,明明上车了最后还是以小赚甚至亏损的结果出局。或者本来可以以小亏出局,结果从小亏损积累成大亏损。所以从这点看,卖出比买入更为重要。简单的说,卖出无非是两种情况:止盈和止损。如果运气很好,买入后价格开始上涨,这时就要考虑止盈的问题,否则可能账面上赚到了钱,没有在合适的位置获利了结,最后平亏出局。如果运气不好,买入后不久价格就开始下跌,这时就要考虑止损了,或者在开仓买入之前就应该考虑好止损的位置,否则小亏损会积累成大亏损。

从统计学的角度看,大部分亏损的单子,在之后的行情里都会回到成本价附近。但是如果遇到一次小概率大幅反向走势,可能会损失之前所有的利润或本金。因此对我们散户来说,可以大赚,可以小赚,也可以小亏,但是永远不能大亏。所以有这么一句话:止损让我们活着,止盈让我们活得更好。

11.1.1 止损的成本

你有没有过这样的经历?当价格朝开仓的反方向移动时,你可能认为是小幅度回调。继续移动时,你可能认为调整这么多了,价格也该反转了吧。但是如果行情继续如此反复下去,一般人能够忍受这样快速且长时间的回撤。这时“止损”也许是多数人心中所想并去执行的。

止损是有成本的,然而,当你止损之后,接着就出现了一段非常暴力又迅速的行情。回头一看。止损止到了低谷。结果明明是赚钱的单子,却以止损提前离场,还白白损失了前几次的试错成本。

面对这种情况,不仅资金缩水,更会有一种被左右愚弄的痛苦。特别连续出现几次这样的情况,对自信心的打击是难以承受的。以至于怀疑自己,为了止损却错失行情而感到不值,久而久之就不再止损。

曾经有家机构做过统计:在止损后,80%多的情况下,价格会重返原点附近。换句话说80%的止损是错误的,不止损的话有80%概率不仅不会亏损,甚至还会小赚。如果把周期拉的足够大,大多数股票、债券、商品、外汇,价格都在一个大的范围内上下波动,毕竟趋势行情的占比还不足三分之一。

那么,在行情中间,无论多,还是空,大部分时候,我们的单子即使被套,只要不止损,总能抗回来。甚至还能获得一些利润。嗯…表面上是这么个理,既然如此,为什么要傻乎乎止损呢。

11.1.2 止损的意义

假如没有止损,却真的碰到反向的大行情。那资金遭到重创,回本岂不更加困难了?我们可以尝试制作一个图表:

亏损率 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
盈利率 11% 25% 43% 67% 100% 150% 233% 400% 900% 本金赔光

如上图,如果在必要的时候没有割肉止损,而是心存侥幸抱着,期待价格能回归。结果可能需要很长的时间才能完成“回本儿”。看完以上,你是不是明白了交易一定要:坚决止损。你下次回归到成本的难度,取决于你上次是否保护了好你的本金。而赚多少取决于市场,亏多少几乎全部取决于自己。

虽然80%的止损都是错误的,但是为了避免80%的错误,不去执行止损,则在剩余的20%的行情中,巧合遇到单边大行情或大调整、大反弹,又是反向,就容易死亡。所以,为了避免20%的小概率的爆仓或大幅亏损的可能,我们却要去选择80%的大概率的止损的错误,这是没有办法的事情。因此,在大部分时候,我们止损,并不是我们方向错了,而是出于控制损失的需要。

在市场里,鳄鱼法则就是:当你发现自己的交易背离了市场的方向,必须立即止损,不得有任何延误,不得存有任何侥幸。鳄鱼吃人听起来太残酷,但市场其实就是一个残酷的地方,每天都有人被它吞没或黯然消失。

11.1.3 止损的本质

止损只是必要条件,而不是充分条件。它只是整个交易系统中的一个分支。前提是有一个正期望的交易系统,否则止损只是让你死的慢些。交易中八成的止损都是因为杂乱无序的波段造成的。

人生和投机一样,大部分都是自己打败了自己。合理的止损需要严格的条件判断,否则频繁的止损只会让人一点点步入失败的泥沼。可以这样说,止损本质上是对市场的敬畏、对不确定性的承认、对市场的尊重。会不会买只是我们能赚多少的因素之一,而会不会止损却是我们能亏多少的全部因素。未来是不确定的,错误的持仓,未必就是错误的方向。止损虽不能决定市场,但是却能界定你面对怎样的市场。

如果把交易比作生活,市场中所有的价格都是合理的,就跟生活一样,存在即为合理。就如同我们无法在生活中决定什么应该存在一样,无法决定市场的价格应该是什么。但我们依然可以决定我们能在生活中做什么,在市场中做什么。在生活中的底线,就如同在市场中的止损一样。

11.1.4 固定比例止盈止损

固定比例止盈止损策略,是一种基于盈利和亏损的比例,设定止盈点和止损点的交易策略。它的思想很简单,该策略基于设定的固定比例来确定止盈和止损点。当价格达到预设的盈利目标时,进行止盈;当价格下跌达到预设的损失限制时,进行止损。为了方便演示,本节课我们使用的都是多头止盈和止损的策略设计,对于空头的止盈止损策略,大家只需要改变少许参数就可以。

这个策略的思路是基于固定百分位止盈止损设计的。对于多头开仓,我们使用的都是当最新价格超越20均线时,进行入场。大家也可以设置别的入场信号,比如macd,双均线等等。具体代码实现是这个样子的:

def main():
    buy_price = None
    take_profit_price = None
    stop_loss_price = None
    mp = 0
    c = KLineChart({"overlay": True})
    p = ext.NewPositionManager()

    while True:
        if exchange.IO("status"):
            LogStatus(_D(), "已经连接CTP!")
            exchange.SetContractType(symbol)
            records = exchange.GetRecords()

            if not records or len(records) < 20:
                Sleep(1000)  # 等待获取足够多的K线数据
                continue

            ma20 = TA.MA(records, 20)

            if mp == 0 and records[-1].Close > ma20[-1]:  # 大于20均线,下多单
                p.OpenLong(symbol, 1)

            pos = p.GetPosition(symbol, PD_LONG)
            
            if pos:
                buy_price = pos['Price']
                mp = pos['Amount']

                take_profit_ratio = 0.005  # 止盈比例
                stop_loss_ratio = 0.005   # 止损比例

                # 根据开仓价计算止盈和止损价格
                take_profit_price = buy_price * (1 + take_profit_ratio)
                stop_loss_price = buy_price * (1 - stop_loss_ratio)

            if mp == 1 and records[-1].Close > take_profit_price:
                Log('止盈时间到')
                p.Cover(symbol)
                buy_price = None
                take_profit_price = None
                stop_loss_price = None
                mp = 0

            if mp == 1 and records[-1].Close < stop_loss_price:
                Log('止损时间到')
                p.Cover(symbol)
                buy_price = None 
                take_profit_price = None
                stop_loss_price = None
                mp = 0

            for bar in records:
                c.begin(bar)
                c.plot(ma20[-1], "均线20")
                c.plot(buy_price, "买入线")
                c.plot(take_profit_price, "止盈线")
                c.plot(stop_loss_price, "止损线")
                c.close()

        else:
            LogStatus(_D(), "未连接CTP!")

            Sleep(1000*60)

首先设置一些变量,包括持仓变量mp,实时买入价格buy_price,止盈价格takeProfitPrice,止损价格stopLossPrice,为了提升交易的成功率,我们这里使用了交易类库,同样这里为了方便画图,使用KLineChart函数。按照固定的流程,首先检查ctp协议是否连接,接着设定合约,然后获取最新的K线数据和Ticker数据。等收集够足够的k线数量后,使用移动平均线(MA)计算20均线(ma20)。

如果当前持仓为空(mp == 0),并且当前Ticker的买入价格大于20均线的最新值,就使用OpenLong执行下多单操作。下单的价格和实时的仓位信息的获取,可以通过GetPosition函数,通过PriceAmount属性,获取实时的买入价格和持仓数量。固定的止盈止损比例是我们自己设定的,这里我们设定止盈比例takeProfitRatio和止损比例stopLossRatio,都是0.005,这两个比例大家可以根据自己的交易理念进行修改。接下来根据买入价计算出止盈价格takeProfitPrice和止损价格stopLossPrice。这就是我们设定的止盈点位和止损点位。

接着进入我们的止盈和止损设计了。对于止盈操作,如果持仓不为空(mp == 1)且K线数据的最新收盘价大于止盈价格,则执行止盈操作。使用交易类库的cover函数进行平仓。由于这一单已经完结,因此可以重新设置买入价,止盈价和止损价都为None,并将mp标记为0表示无持仓。对于止损操作,如果持仓不为空(mp == 1)且K线数据的收盘价小于止损价格,则执行止损操作。止损平仓操作完成,同样重新设置mp,买入价,止盈价和止损价。最后,使用KLineChart函数,将20均线、买入价、止盈价和止损价绘制在图表上。循环进行上述操作,实现实时的交易决策和止盈止损操作。

在回测结果中可以看到,我们设置周期为分钟,当达到开仓条件,会执行开仓的操作,并且设置相对应的止盈和止损线,当最新的价格达到固定比例的止盈或者止损价格的时候,会进行对应的止盈或者止损的平仓操作。总体来说,这个策略通过固定百分位止盈止损设计,根据价格与均线的关系进行交易决策,并且根据买入价设定止盈和止损价格,以限制风险和保护收益。除去固定比例之外,我们也可以使用固定的点位变化进行固定点数止盈止损操作。当盈利或者亏损达到一定点数之后,进行迅速的平仓,实现止盈止损的目的。

11.1.5 移动止盈止损

固定的比例或者点位进行止盈止损有时候太过于死板。当我们主动止盈时,可能会遇到一大波行情,只赚到其中一小部分就错过了后续更大的利润。虽然这样的交易并不亏损,但心理上会有一种错失良机的遗憾感。为了解决这个问题,移动止盈止损策略采用了浮动止损的方法,就是在获得不同级别的浮动盈利之后,开启下一级主动止损模式。这样一方面可以持续享受较高的浮动盈利,同时也不断提高止损点位,用来实现更多盈利的目标。这个策略实际上只有止损,没有止盈,随着盈利比例的移动,止损点也随之更新。这样可以更好地抓住市场的趋势,同时尽量的减少亏损。

这个策略是一个移动止盈止损的交易策略。下面是这个策略的思路:

  • 初始化一些变量,包括持仓状态(mp)、开仓价格(buy_price)、初始盈利比例(takeProfitRatio)和止盈止损比例(stopLossRatio);
  • 固定程序,连接交易所,获取K线和行情数据。检查K线数据数量;
  • 计算20日均线(ma20);
  • 空仓状态(mp == 0)使用20均线下多单/空单,记录开仓价格并将持仓状态置为持仓(mp = ±1);
  • 根据初始盈利比例和止盈止损比例计算盈利价格(takeProfitPrice)和止损价格(stopLossPrice),对于多头来说,是开仓价格乘以(1+盈利比例);对于空头来说,是开仓价格乘以(1-盈利比例),相应的止盈止损价格是盈利的价格乘以(1±止盈止损比例);
  • 如果当前处于持仓状态(mp == 1)且最新的收盘价大于(多头)/小于(空头)止盈价格,就要更新盈利比例,并更新盈利价格和止盈止损价格。

这里的关键是盈利比例和止盈止损比例的更新。首先通过条件判断确认当前处于持仓状态且当前收盘价上穿/下穿上一个阶段的盈利价格。如果满足条件,那么表示达到了新的盈利点,打印“达到新的赢利点,更新比例和价格”。接着,将止盈比例(takeProfitRatio)增加0.005。根据新的止盈比例,更新止盈价格(takeProfitPrice),对应的止盈止损价格也会相应更新。

根据新的止盈价格和止损比例,更新止损价格(stopLossPrice)。所以当价格呈现一定的上涨/下跌趋势,止盈止损的价格也会一直对应提升/下降。一旦出现当前处于持仓状态且最新的收盘价小于(多头)/大于(空头)止损价格的状况时,就会平仓并退出交易,重置开仓价格和相关变量。最后使用KLineChart进行绘图的操作。

该策略的核心思想是根据价格与均线的关系判断买入和卖出时机,并根据盈利情况逐步调整比例和止盈止损比例。在回测结果中可以看到,当价格达到新的盈利价格时,会增加盈利比例并更新盈利价格和止盈止损价格,从而保护已实现的盈利。而当价格达到止盈止损价格时,就会平仓并退出交易,可以限制损失。图表中我们也可以看到,相对于固定的止盈和止损点位,移动的止盈和止损线是会实时更新的。

通过使用移动止盈止损策略,我们可以更加灵活地应对市场变化,逐步提高止盈点位以获取更多的收益。这种策略能够在保护利润的同时,也给予市场更多的空间,以便捕捉更大的行情。当然,在实际操作中,需要基于市场情况和自身风险承受能力进行合理的设置和调整。总之,通过采用浮动止损的移动止盈止损策略,我们可以在控制风险的同时,最大限度地提高利润。这种策略的灵活性和适应性,使得我们能够更好地应对市场的变化。

def main():
    mp = 0  # 持仓状态,0表示空仓,1表示持仓
    buy_price = None  # 开仓价格
    takeProfitPrice = None
    stopLossPrice = None
    takeProfitRatio = 0.005  # 初始盈利比例
    stopLossRatio = 0.01  # 初始止盈止损比例
    p = ext.NewPositionManager()
    c = KLineChart({"overlay": True})

    while True:
        if exchange.IO("status"):
            LogStatus(_D(), "已经连接到CTP!")

            exchange.SetContractType(symbol)
            records = exchange.GetRecords()

            if not records or len(records) < 5:
                Sleep(1000)  # 等待获取足够多的K线数据
                continue

            ma20 = TA.MA(records, 5)  # 计算20均线

            if mp == 0 and records[-2].Close > ma20[-2]:  # 大于20均线,下多单
                p.OpenLong(symbol, 1)

            if mp == 0 and records[-2].Close < ma20[-2]:  # 小于20均线,下空单
                p.OpenShort(symbol, 1)

            pos = exchange.GetPosition()

            if pos and pos[0].Type % 2 == 0:
                buy_price = pos[0].Price
                mp = pos[0].Amount

                takeProfitPrice = buy_price * (1 + takeProfitRatio)  # 计算盈利价格
                stopLossPrice = takeProfitPrice * (1 - stopLossRatio)  # 计算止盈止损价格

            if mp == 1 and records[-1].Close > takeProfitPrice:
                Log("达到新的赢利点,更新比例和价格")
                takeProfitRatio += 0.005  # 增加盈利比例
                takeProfitRatio = _N(takeProfitRatio)  # 格式化浮点数
                takeProfitPrice = buy_price * (1 + takeProfitRatio)  # 更新盈利价格
                stopLossPrice = takeProfitPrice * (1 - stopLossRatio)  # 更新止盈止损价格
                Log("更新盈利比例:", takeProfitRatio)
                Log("更新止盈止损比例:", stopLossRatio)

            if mp == 1 and records[-1].Close < stopLossPrice:
                Log("达到止盈止损点,平仓并退出交易")
                p.Cover(symbol)
                buy_price = None  # 重置
                takeProfitPrice = None
                stopLossPrice = None
                takeProfitRatio = 0.005
                stopLossRatio = 0.01
                mp = 0

            if pos and pos[0].Type == 1:
                buy_price = pos[0].Price
                mp = pos[0].Amount * -1

                takeProfitPrice = buy_price * (1 - takeProfitRatio)  # 计算盈利价格
                stopLossPrice = takeProfitPrice * (1 + stopLossRatio)  # 计算止盈止损价格

            if mp == -1 and records[-1].Close < takeProfitPrice:
                Log("达到新的赢利点,更新比例和价格")
                takeProfitRatio += 0.005  # 增加盈利比例
                takeProfitRatio = _N(takeProfitRatio)  # 格式化浮点数
                takeProfitPrice = buy_price * (1 - takeProfitRatio)  # 更新盈利价格
                stopLossPrice = takeProfitPrice * (1 + stopLossRatio)  # 更新止盈止损价格
                Log("更新盈利比例:", takeProfitRatio)
                Log("更新止盈止损比例:", stopLossRatio)

            if mp == -1 and records[-1].Close > stopLossPrice:
                Log("达到止盈止损点,平仓并退出交易")
                p.Cover(symbol)
                buy_price = None  # 重置
                takeProfitPrice = None
                stopLossPrice = None
                takeProfitRatio = 0.005
                stopLossRatio = 0.01
                mp = 0

            for bar in records:
                c.begin(bar)
                c.plot(ma20[-1], "均线20")
                c.plot(buy_price, "买入线")
                c.plot(takeProfitPrice, "止盈线")
                c.plot(stopLossPrice, "止损线")
                c.close()

            Sleep(1000)
        else:
            LogStatus(_D(), "未连接CTP!")
            Sleep(1000)

11.1.6 动态止盈止损

动态止盈止损策略利用技术指标或其他市场信号来确定止盈和止损点。通过分析市场趋势指标,决定何时进行止盈和止损操作。因为指标实时计算的,所以这种策略能够根据市场情况作出灵活的决策。移动止盈止损和动态止盈止损虽然有些相似,但在概念和实施方式上存在一些区别。移动止盈止损是通过逐步调整止盈和止损点位的数值来实现的。比如,当获得一定的浮动盈利后,将止盈点位从初始设定的水平A移动到更高的水平B,以获取更多的利润。而动态止盈止损是根据市场行情和交易情况进行实时调整的。对于止盈点位,可以根据技术指标或者其他因素来设定触发条件,当满足条件时进行止盈操作。对于止损点位,可以根据风险管理原则和市场情况来灵活设定。

动态止盈止损的策略有很多种,以下是其中几种常见的策略:

  • 移动平均线策略:这个大家都很熟悉,该策略利用移动平均线来确定止盈和止损点位。
  • 波动带宽策略:这个前面我们也讲解过,代表策略是布林带等波动带宽指标,来确定止盈和止损点位。
  • 技术指标策略:该策略使用技术指标作为判断依据来设定止盈和止损点位。常用的技术指标包括相对强弱指标(RSI)、移动平均收敛/扩展指标(MACD)等。根据技术指标的信号来调整止盈和止损点位,例如当RSI超过一定阈值时设定止盈点位,低于一定阈值设置止损点位。
  • 支撑阻力位策略:该策略基于价格的支撑位和阻力位来设定止盈和止损点位。

我们来举例一个波动性止盈止损策略。当市场波动性较高时,设定较宽松的止盈和止损点;而当市场波动性较低时,设定较紧密的止盈和止损点。这样可以根据市场行情的不同情况来动态调整止盈止损的幅度。

波动性止盈止损的原理是这样的:

  • 波动性测量:首先,需要度量市场的波动性。常用的指标包括标准差、平均真实范围(ATR)等。这些指标可以帮助确定价格的波动范围。

  • 止盈/止损点位:接着根据波动性指标,可以设定一个合理的止盈/止损点位。止盈/止损点位应该超过当前价格的波动范围,以确保能够捕捉到足够的利润和限制损失。例如,可以将点位设定在标准差或ATR的倍数之外。

随着市场的波动性变化,波动性止盈止损策略的止盈和止损点位是动态调整的。例如,如果市场波动增加,可以适当扩大止盈和止损点位;如果市场波动减小,可以适当缩小止盈和止损点位。

import talib

def main():
    mp = 0
    buy_price = None
    takeProfitPrice = None
    stopLossPrice = None
    c = KLineChart()
    p = ext.NewPositionManager()

    while True:
        if exchange.IO("status"):
            LogStatus(_D(), "已经连接CTP !")
            exchange.SetContractType(symbol)
            records = exchange.GetRecords()
            
            if not records or len(records) < 20:
                Sleep(1000) # 等待获取足够多的K线数据
                continue
            
            ma20 = TA.MA(records, 20)

            if mp == 0 and records[-1].Close > ma20[-1]: # 大于20均线,下多单
                p.OpenLong(symbol, 1)

            if mp == 0 and records[-1].Close < ma20[-1]: # 小于20均线,下空单
                p.OpenShort(symbol, 1)

            pos = exchange.GetPosition()

            if pos:
                buy_price = pos[0].Price

                #使用条件表达式(三元操作符)来决定乘以1还是-1
                mp = (pos[0].Amount * 1) if (pos[0].Type % 2 == 0) else (pos[0].Amount * -1)

            stdValue = talib.STDDEV(records.Close, 14)[-1] # 计算标准差
    
            # 根据开仓价计算止盈和止损价格
            upperPrice = buy_price + 2 * stdValue # 两倍标准差区间
            bottomPrice = buy_price - 2 * stdValue

            if mp == 1 and records[-1].Close > upperPrice: 
                Log('多头止盈时间到')
                p.Cover(symbol)
                buy_price = None # 重置开仓价格
                takeProfitPrice = None
                stopLossPrice = None
                mp = 0

            if mp == 1 and records[-1].Close < bottomPrice: 
                Log('多头止损时间到')
                p.Cover(symbol)
                buy_price = None # 重置开仓价格
                takeProfitPrice = None
                stopLossPrice = None
                mp = 0

            if mp == -1 and records[-1].Close < bottomPrice: 
                Log('空头止盈时间到')
                p.Cover(symbol)
                buy_price = None # 重置开仓价格
                takeProfitPrice = None
                stopLossPrice = None
                mp = 0

            if mp == -1 and records[-1].Close > upperPrice: 
                Log('空头止损时间到')
                p.Cover(symbol)
                buy_price = None # 重置开仓价格
                takeProfitPrice = None
                stopLossPrice = None
                mp = 0

            for bar in records:
                c.begin(bar)
                c.plot(ma20[-1], "均线20", overlay = True)
                c.plot(buy_price, "买入价格", overlay = True)
                c.plot(upperPrice, "区间上限", overlay = True)
                c.plot(bottomPrice, "区间下限", overlay = True)
                c.plot(stdValue, "标准差", overlay = False)
                c.close()
            
        else:
            LogStatus(_D(), "未连接CTP !")

这个代码是一个基于波动止盈止损的简单示例策略,适用于期货交易市场。同样使用20均线作为做多和做空的操作。使用标准差来计算止盈和止损价格。标准差是衡量价格波动性的指标,这里取当前标准差的两倍作为波动上限和波动下限的价格区间。

实时波动性体现在这段代码中的两个方面:标准差(std):在代码中使用了 talib.STDDEV() 函数计算标准差,以衡量价格的波动性。标准差是一种统计指标,用于测量数据的离散程度或波动性。通过计算价格数据的标准差,代码可以获取最近一段时间内价格的波动性信息,这里使用了当前标准差的两倍作为波动上限和波动下限,即买入价加上两倍标准差和减去两倍标准差。通过实时计算标准差并基于标准差设置多头和空头相应的止盈和止损价格,代码可以根据实时价格的波动性进行交易决策。如果当前价格达到相应的止盈价格和止损价格时,就进行相应的交易操作。这样就能够根据实时波动情况进行风险控制和收益保护,提高交易的效果。

可以在回测结果中看到,止盈和止损之间的距离并不是固定不变的,会随着价格的波动程度,区间进行动态的调整,因此在一定程度上具有更强的适用性。这里的标准差周期(period)和标准差倍数(multiple)都是可以实时调整的,可以针对于不同种类的期货品种,例如波动性较大的化工类(纯碱,甲醇等),和波动性较小的农产品类(玉米和淀粉类)进行参数的调整。

以上我们讲了三种止盈止损的设计,大家也不一定要严格纠结于这些概念的区别,并且市面上还存在许多止盈止损策略,重要的是理解这些策略的思想,以及如何用代码实现这些策略。希望通过本课程的学习,大家可以了解止盈止损策略的基本原理,理清其思路,并根据自己的交易理念,构建更适合自己的止盈止损策略。希望本课程能为你提供有益的指导和启发,帮助你在交易中更加有效地运用止盈止损策略。

11.2 建立概率思维,提升交易格局

期货有很多种交易方法,无论是价值投资、技术分析、事件热点、套利对冲等,表面上看起来逻辑严谨,但实际上往往相互矛盾。价值投资的优势是可以根据价值给价格波动划分一个安全边际,技术分析的优势是三大假设使交易具有一定的科学性。

但它们都有一个共同的特点,那就是对未来的价格分析,只能做到大概预测,而不能精准预测。即使将基本面分析与技术分析相结合,也不能解决提高“精准”的问题,所以自始至终交易都是一个概率游戏。

11.2.1 交易来自生活

不仅如此,人这一生,小到过马路,交什么样的朋友;大到从事什么样的事业,跟什么人结婚等等,都是评估风险与回报的概率游戏。因为我们没有未卜先知的能力,每做一件事即使再有把握,风险都始终存在,无法做到百分之百是对的。

许多人在交易中犯错的重要原因就是缺少概率思维,在做交易时过于感性而非理性。感性其实就是我们的原始本能,在市场中,这些原始本能可以激发人的许多弱点,并且成倍放大。

11.2.2 概率思维

概率思维,是一个文绉绉的名字,说得通俗点就是——赌博思维。“赌博”可能是被人们误解最深的词汇之一了。如果你的策略是负期望,就是赌徒;如果你的策略是正期望,就是赌博。

如果把“赌博”中的贬义去掉,将之理解为承担一定风险而获得一定回报的活动,那么人生真的处处是赌博。上学选择哪个专业、买不买房、项目上不上马、打工还是创业等等。甚至把钱存到银行也是赌博,因为你不确定未来是否会通货膨胀,银行是否会破产(参考希腊债务危机)。总之从摇篮到坟墓,生命的每个过程都是在赌博。

11.2.3 久赌必赢

在研究久赌必赢策略之前,先来研究一下,那些久赌必赢策略的原理。除了印钞机,还有什么是能久赌必赢的呢?

赌场里面的:百家乐、轮盘赌、老虎机、21点等等,不管怎样变换形式,都隐藏着一个赌场从来不说的秘密:就是在1比1的赔率下,庄家的胜率总是大于50%;另外,还有一种赔率很高胜率很低的赌博产品。就这样,赌场老板利用「大数定律」,持续不断地参与这样的游戏,那么长期一定是盈利的。

举个例子,三个骰子,押大小,4-10是小,11-17是大,押对了就赢钱。而骰宝有一种围


更多内容

by2022 企业微信加不上啊啊啊啊啊啊

雨幕(youquant) 您好,企业微信满了,您加这个微信: https://www.youquant.com/upload/asset/1780ac4e8b9064c9d7d9a.png