Python-卖空算法教程-全-

Python 卖空算法教程(全)

原文:zh.annas-archive.org/md5/ceefdd89e585c59c20db6a7760dc11f1

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

"没有比一个时机已经成熟的理念更加强大的了。"

– 维克多·雨果

市场参与者总是希望行业变得更加高效:“去除中间人”,“降低成本”,“合理化”。我们终于尝到了我们自己的药。市场长期*均回报率为每年 8%。然而,大约 60%的专业基金经理年复一年地表现不佳。90%的散户投资者都失败了。我们交易的方式显然不起作用。尽管充满了傲慢自大,但金钱的皇帝们却一直在赤裸裸地游行。如果我们想要在这个市场达尔文主义中生存下来,我们就必须共同进化。进化不会留下任何囚犯。

全球变暖是金融服务领域的现实。积极管理的资金冰川正在融化。共同基金面临着来自交易所交易基金降低费用的巨大压力。幸运的是,一直以来我们的眼皮底下就有一个terra incognita,人类从未踏足的未知领域。

如果我们把所有关于投资、交易、市场的书都堆在一起,去月球的旅行将成为一个悲伤的生态现实。然而,如果我们把有关做空交易的书籍一字排开放在餐桌上,那么仍然会有足够的空间放一瓶库特罗蒂酒,一瓶神圣的北罗纳山谷西拉-维奥涅白葡萄酒,和几杯酒。做空交易是提高和维持资产管理规模的关键。当市场暴跌时,仍然站得住的人脱颖而出。资金可能暂时流向(和流出)那些在牛市中表现出色的人,但它将永远倾向于那些在熊市中表现出色的人。投资者可能会忘记不那么出色的回报,但他们不会原谅回撤。

做空交易收取高额费用。假设你在濒临破产的纯做多共同基金中添加了一本做空账面。从那一天起,你就可以收取高额管理费,甚至要求高昂的绩效费用。你将在交易异国情调的工具时享有更多自由,有权保持更高的现金余额,自由选择性地披露你的持仓。而自由的代价就是学会做空。

这本书是为谁而写的

这本书是由一位从业者为从业者撰写的。它适用于高级到专家级的市场参与者。即使你从未在 Python 中编写过一行代码,这本书仍然适合你。它最初是没有源代码的。后来的补充是为了帮助读者在现实生活中实施这些概念。如果你是一个经验丰富的编程人员,但对市场还很新,你将会掌握一些对你的旅程有帮助的概念。然而,你可能希望通过进一步阅读来补充你的市场教育。

即使你选择永远不卖空,本书仍然适合你。为卖空一侧开发的工具和技术是经受住极端条件的。如果你能在卖空一侧的干旱环境中生存,想象一下你将如何在买空一侧蓬勃发展。如果你从事长/短业务,问题不是你是否应该阅读本书。真正的问题是你是否能承受阅读本书的代价。你可能不同意一些观点,但它们会引发思考并引发讨论。我们最初抵制的想法是使我们成长的想法,所以欢迎来到你舒适区之外的空间。

本书涵盖内容

第一部分内部游戏:揭秘卖空

第一章股市游戏,讨论了几个问题:“股市是一门艺术还是一门科学?如果它只是一场游戏呢?你如何赢得一场无限复杂的随机游戏?”本章设定了本书的背景。

第二章关于卖空的 10 个经典谬论,驳斥了有关卖空的持久谬论。最重要的问题是:“你想靠数字还是故事退休?”如果是前者,那么卖空者就是你养老金的最好朋友。

第三章走进狂野的卖空,解释了长期思维方式在卖空上的弧线及其可预测的失败。本章描述了卖空的三个固有挑战:市场动态、稀缺心态和信息不对称。

第二部分外部游戏:打造稳健的交易边缘

第四章长/短方法论:绝对与相对,探讨了创意的生成。在短期内,你能够持续产生与长期相当多,甚至更多的想法。

第五章制度定义,解释了几种制度定义方法,将股票重新分类为看涨、看跌或无法确定的。

第六章交易边缘是一个数字,这就是公式,旨在揭开神秘的、神秘的、神奇的交易边缘。无论是什么资产类别和时间跨度,都只有两种策略。我们解释了每种策略的利弊。

第七章提升您的交易边缘,概述了提高回报分配和构建稳健交易边缘的七种方法。

第八章头寸规模:金钱是在资金管理模块中赚到的,证明了金钱是在资金管理模块中赚到的。我们介绍了一种改变游戏规则的股价曲线交易方法。

第九章风险是一个数字,介绍了四个无愧的衡量稳健性的风险指标。卖空者是出色的风险管理者。

第三部分长/短游戏:打造长/短产品

第十章精细化投资宇宙,解释了一些常见的避坑陷阱,以及投资者希望解决的问题,以帮助将大量股票精简为可投资的范围。这一章为本书的最后部分铺*了道路。

第十一章长/短工具箱,深入探讨了管理长/短组合的四个最重要的杠杆。现在我们知道客户想要什么,我们来看看可用于实现这些目标的工具。

第十二章信号与执行,汇集了前几章涵盖的概念,并讨论了构建长/短投资产品时的信号处理、执行和其他重要组成部分。

第十三章投资组合管理系统,探讨了你武器库中最被低估的工具之一。现在你已经添加了一个相对短的书籍,到目前为止你一直在使用的任何工具都迫切需要进行彻底的升级。本章介绍了在设计自己的投资组合管理系统时会有所帮助的主题。

附录股票筛选,提供了一个股票筛选工具,它将解决市场参与者最为关注的理念生成问题,并允许你将学到的一切付诸实践。

为了充分利用本书

有时我们赢,有时我们学。从本书中获得最大收益的最佳态度是在市场上亏钱。这将使你保持一种开放的思维状态!

对 Python 的中级知识,特别是对numpypandasmatplotlib的使用就足够了。我们还会使用一些非标准的 Python 库;yfinancescipy。此外,还需要具备高中水*的代数和统计知识。

下载示例代码文件

本书的代码包也托管在 GitHub 上,网址为github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python。我们还提供了来自我们丰富书籍和视频目录的其他代码包,可以在github.com/PacktPublishing/下载。快去看看吧!

下载彩色图片

我们还提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图片。你可以在这里下载:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf

使用的约定

本书中使用了许多文本约定。

CodeInText:指示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄。例如:“从rolling_profitsrolling_losses函数中计算profit_ratio。”

一段代码设置如下:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt 

任何命令行输入或输出都如下所示:

3.52 

粗体:表示一个新术语、一个重要词或屏幕上看到的词,例如,在菜单或对话框中,也会在文本中显示为这种格式。例如:“价格是否击败了加权*均价格成交量VWAP)?”

警告或重要说明如下所示。

提示和技巧显示为这种格式。

第一章:股票市场游戏

“无限游戏有无限的时间跨度。因为没有终点线,游戏没有实际结束,所以不存在“赢得”无限游戏的概念。在无限游戏中,目标是保持游戏进行,延续游戏。”

– 西蒙·西尼克

金融服务业正面临严重的存在危机。融资活跃管理资产融化的速度比北极冰盖还要快。进化不留俘虏。如果主动管理者不想成为濒危物种名单上的蓝鳍金枪鱼的一员,那么学会做空可能是一个不可多得的技能,可以加入到他们的武器库中。正如 2007 年至 2008 年全球金融危机向我们展示的那样,市场参与者不仅需要在牛市中实现盈利,而且需要在熊市中实现盈利至关重要。为此,本书将介绍做空的方方面面,并制定算法策略以最大化其有效性,最终目标是创建一个稳健的投资产品,使您与市场竞争对手区分开来。

本章为本书铺*了道路。在你的职业生涯中的某个时刻,你可能会想知道市场更像是一种科学还是一种艺术形式。如果市场是一个永无止境的、无法解决的谜题呢?你如何赢得一个无限、复杂、随机的游戏?

我们将涵盖以下主题:

  • 股票市场是艺术还是科学?

  • 你如何赢得这个复杂、无限、随机的游戏?

  • 玩做空游戏

股票市场是艺术还是科学?

“当银行家们聚餐时,他们谈论艺术。当艺术家们聚餐时,他们谈论钱。”

– 奥斯卡·王尔德

从前,洛伦佐·德·美第奇赞扬米开朗基罗的手工艺品质。伊尔·迪维诺回答伊尔·玛格尼菲科说:“只有那些还没有努力工作到看到工艺的人才会认为它是艺术。”

每个市场参与者都曾想过股票市场更像是一种艺术还是一种科学。艺术背后的假设是天赋的概念。一些人天生就有天赋。有些人没有,我就是其中之一。如果天赋是与生俱来的,那么我们这些凡人只能接受我们根本没有。然而,天赋常常是懒惰的借口。迈克尔·乔丹并不是天才。他曾被踢出篮球队,所以他训练,直到他能够连续命中 100 个罚球为止才会回家。命中了 98 个?哦,不好意思。再来一次。这样,技能就可以被发展。产出可能看起来像是毫不费力的优雅。然而,这需要技艺、努力、毅力,以及安吉拉·达克沃斯称之为“毅力”的东西。

在市场上赚钱不是艺术,而是一种技能。在 80 年代初,理查德·丹尼斯和威廉·艾克哈特组建了一个团队,其中包括一名扑克玩家、一名毒贩和来自各行各业的其他人。他们被赋予了一个系统、起始资金,并被派去交易期货。几十年后,其中一些人仍在交易。他们是有天赋的吗?也许其中一些人有一些先天倾向,但这并不重要。他们研究并努力实施了一个系统,其结果可能看起来像艺术品。

科学家喜欢用明确的公式来解释世界。这种方法对于简单甚至复杂的系统都很有效(通常可以将其分解为几个简单的系统),但对于复杂系统则不适用:

  • 简单系统:你需要多少燃料才能把火箭送到火星?

  • 复杂系统:如何将某人送到火星?(这可以分解成简单的系统,比如燃料消耗。)

  • 复杂系统:如何在火星上维持生命?

市场是复杂的系统。与复杂系统不同,复杂系统不能被分解为一系列简单的系统。当你认为自己有一个明确的公式来解释股价时,市场会适应并变成其他形式。

我要表达的观点是,我们看到的事物并不是它们的本来面目。我们看到的是我们认为它们是的样子。背景信息过滤了我们的感知。如果我们认为某事会很难,那很可能不会容易。

如果我们认为股市是一种艺术,我们会对杰作感到惊叹,但无法欣赏工艺。如果我们把它看作是一门科学,我们将寻找一个明确的公式,却一次又一次地被随机性所愚弄。如果我们把它看作是一场游戏,那么我们内心的孩子会参与其中。

如何赢得这个复杂、无限、随机的游戏?

“已知已知”是我们知道自己知道的东西;而“已知未知”是我们知道自己不知道的东西。但也有“未知未知”,那就是我们不知道自己不知道的东西。

– 唐纳德·拉姆斯菲尔德

股价可能随时间反映基本面,但旅程可能是一次随机行走。随机行走理论由伯顿·马尔基尔在《华尔街的随机漫步》中得到推广。它基本上假设每种金融资产都有一定的内在价值,然而市场价格很难准确预测。随机性经常使市场参与者迷失方向。即使是业内最优秀的人成功的概率也大约是 50%,唯一的结论是无法消除随机性。

有两种类型的游戏:有限和无限。有限游戏有明确的规则、参与者、开始、中间和结束。无限游戏没有一套规则、没有开始和结束。有限游戏的目标是赢得游戏。无限游戏的目标是留在游戏中。

让我们举个例子来说明这一点。一名职业扑克玩家遇到了一名职业交易者。交易者整晚都在打高风险的牌并赢得了比赛。第二天,扑克玩家买了交易者推荐的一只股票。两周后,交易者停止了交易,而赌徒却忘记了这件事,并在接下来的 3 年里把钱翻了一番。对于交易者来说,扑克是一种爱好,他赢得了扑克夜,因为他知道自己能承受更多的风险。与此同时,扑克玩家采取了有计划的风险。他接受了短期损失作为赢得长期游戏的一部分。当扑克玩家遵循投资提示时,他将其经历了起起落落,因为他只是使用了可支配的资产。另一方面,当交易者关闭同样的股票并错过随后的涨势时,他正在执行风险管理。

对于交易者来说,扑克夜是一个有限的游戏。另一方面,对于扑克玩家来说,股票提示是一个有限的游戏。他们在彼此的游戏中都可以承受更高的风险容忍度,因为他们知道游戏是有限的。然而,当游戏从爱好变成生活方式时,我们变得更加风险厌恶。

畅销书系列《市场魔法师》的作者杰克·施瓦格经常说,没有一个理智的人会买一本外科手术的书,周末读完,然后相信自己周一就能准备好给人动手术。然而,人们会买投资书籍,订阅一两份通讯,然后认为在周一开始交易是完全合理的。这可能对于有着非常小样本的业余爱好者有效。毕竟,有一半的机会是赢的。对业余爱好者有利的随机性对于有着更大样本的专业人士来说是有害的。当一个爱好变成工作时,游戏就变得无穷了。赌徒可能已经为每年几个糟糕的扑克夜预算好了。同样地,交易者遵循严格的风险管理政策。扑克玩家和顶尖交易者有一个共同点:他们都去工作;这不应该是有趣的。

这引出了本书的核心问题:你如何打败一个无穷复杂的随机游戏?

如何赢得无穷的游戏?

如果你参与了一个无穷游戏,你不是通过赢得一个游戏或所有游戏来取胜。你是通过留在游戏中来取胜。你赢了一些,输了一些,但只要你的*均胜率乘以你的胜率大于你的*均损失乘以你的损失率,你就能留在游戏中。只要你的盈利期望保持正值,你就能赢。作为一名股票选择者、交易者、投资者、投机者,或者无论你选择称呼自己为什么,你的工作就是最大化这个盈利期望。这部分是你挑选的所有股票中,你保留的那些股票必须看起来不错的部分,其结果最终可能看起来像艺术品。这就是我们将在第二部分外部游戏:发展健壮的交易优势中努力的内容,所以继续阅读吧,米开朗基罗。

如何打败复杂性?

当面对一个复杂问题时,我们直觉上认为解决方案必须复杂化。并非总是如此。一个快速抛射物的轨迹是火箭科学,确实如此。现在,你上一次看到塞雷娜·威廉姆斯在球场边解决随机方程式是什么时候?这就是所谓的凝视启发式:看,跑,拦截,重复。复杂的问题有简单的解决方案。

许多量化交易者,亲切地称为量化交易员,认为他们必须用费解的方程式证明他们的博士学位。通过数学恐吓来证明无疑会激发自尊心,但高智商并不总是与高绩效相称。股市是诺贝尔奖获得者走来受挫的地方。

另一方面,似乎有一个简单的启发式法则就隐藏在明处,它击败了市场的复杂性。这个简单的口号是:“止损,放大赢家。” 第二部分外部游戏:发展稳健的交易优势,将提供减少输家的负面影响的实用技术。

如何击败随机性?

作为一个物种,我们的生存取决于我们如何处理随机性。我们在日常生活中本能地应用的同样生存机制并不转移到市场中。理解随机性对于培养健康的卖空实践至关重要。首先,让我们看看我们如何在市场中处理随机性。其次,让我们看看我们如何在现实生活中处理随机性。第三,我们将看到如何将这种技能应用到市场中。

假设我们设计一个挑选股票的系统。当我们构建策略时,我们从一些假设开始。如果股票符合某些预期[在此插入一长串标准...],我们就做多或做空。在理论上,高估值,远远超出合理市场预期的股票将恢复到“公*”,公*估值是一些市场参与者愿意为他们所感知的价值支付的价格。在理论上,糟糕的企业有望破产。在理论上,超买的股票有望回归到*均水*,超卖问题则相反。在理论上,这应该奏效。现在,是时候尝试这个想法了。随机性可以总结在下面的结果矩阵中:

图 1.1:比喻矩阵结果

真正的阳性是指结果符合预期的情况。真正的阴性是指股票未能通过我们的测试,并且如预期的那样表现糟糕。这是理论与现实的第一次交锋。在理论上,市场是有效的:所有公开可用的信息应该立即反映在价格中。但在实践中,情况并非总是如此。

回到起点,当结果不符合期望时(例如,股票通过了我们的测试但在实践中却失败了),存在假阳性,这表明我们遗漏了某些东西。在实践中,估值可以变得更加丰厚并且维持时间更长,而客户却不会一直投资。在实践中,超买和超卖的技术指标是持续强势和弱势的迹象,分别表示趋势的延续而不是回归到*均水*。我们感到困惑和沮丧。我们的自然倾向是完善我们的论点,增加复杂性以减少假阳性。这种方法会产生更少的信号,但假阳性并没有完全消失。

对于中级超卖的短线卖空者来说,过度过滤的一个副作用和经典陷阱是假阴性。这是指股票表现出期望的行为,但由于我们更严格的测试而完全未被发现。现实生活中的类比是通过清单约会。有时人们带着一长串不可实现的标准和不切实际的期望出现。同样,市场参与者经常因为他们自己的自我限制信念系统而拒绝足够好的想法。他们实质上是在寻求他们的选择将如预期般执行的保证,通过应用多余的过滤器,但他们没有意识到其中一些条件是互斥的或不切实际的。因此,他们系统性地定价自己脱离市场,并错过了所有完全正常的机会。这解释了图 1.1中假阴性圈的膨胀大小。

结构/拥挤的空头是过度过滤的典型例子。他们勾选所有的坏项目,除了显而易见的交易很少盈利。相反,高股息率价值陷阱是假阴性或盲点的典型例子。这些股票具有便宜的估值和股息支持。它们不参与牛市。在长期的熊市中,它们也不能提供足够的支持。它们是慢燃的表现不佳者,被排除在被遗忘的问题的炼狱之外。最重要的是,尽管我们尽了最大努力,一些股票仍然无法盈利,无论是在空头还是多头方面。这比我们最初想象的要复杂得多。更多的困惑。又回到起点。

在继续使用清单约会场景的情况下,战胜随机性的一种方法如下。在纸上,一个人勾选所有项目。实际上,大红旗出现了:那个人不笑你的笑话,讨厌西兰花,顽固地拒绝与你的金鱼辩论康德的《纯粹理性批判》——所有经典重要的事情。

在现实生活中,你要处理这种看似随机的反应就像中止任务一样。你不会等到结婚并带着一对孩子,一个死掉的金鱼在鱼缸里,冰箱里堆满了蔬菜才决定分手。市场也是一样。一只股票可能符合所有标准,但可能会出现一些意外或被忽视的情况,你会选择退出。当我们将所有精力都集中在选股上时,我们试图用确定性解决随机性。下次努力选择正确的股票并不能解决随机性。完美主义是一种拖延症。处理随机性的唯一方法是接受我们的错误。我们失败得越快,我们就能越快地前进。

让我们通过一个实际的例子来说明这个概念。我们都可以同意,相对于指数表现不佳的股票已经达到了顶峰。在达到顶峰的群体中,有 100% 的未来表现不佳者(这将是我们空头卖出的主要目标),还有一些股票将会徘徊不前,直到再次趋势。没有简单的方法来区分前者和后者。然而,有一些简单的技巧来处理"吃白食"者。击败随机性的方法不是试图成为一个更好的选股人。击败随机性的方法是接受在某个时候,你会选到失败者,并学会如何处理他们。人们看到所有那些在市场上表现出色的人只是因为他们在选股时做出了正确的选择。他们没有看到那些在这条道路上被丢弃的不那么赚钱的选择。我们的看法是颠倒的。我们希望在比赛之前就获得奖牌。伟大的选股人应该根据他们选择留下来的东西来评判,而不是根据他们在这条路上丢弃的不那么赚钱的选择。

玩空头卖出游戏

"跟我来如果你想活下去。"

– 阿诺德·施瓦辛格,终结者

空头卖出的机制看似简单。例如,你以 100 的价格卖出一只股票,以 90 的价格买回,然后获得 10 的利润。它可以绝对或相对于一个基准。在进行空头交易之前只需要进行一个额外的步骤。空头卖家出售他们没有拥有的股票。因此,他们首先从他们的经纪公司的股票借贷台借出这些股票。一旦他们买回股票并*仓,他们就会归还这些股票。

不要让这种简单性愚弄你。由于我们在本章中考虑的游戏的无限,复杂,随机性质,90% 的市场参与者失败。剩下的 10% 中,不到一半的人会参与空头卖出。这是市场的毫不妥协的现实。

我们的目标是应对这些挑战,并在投资组合的两侧取得成功,尽管情况复杂。如果我们跟随大多数人走的路,我们最终会得到相同的结果,减去一个标准差以作良好的衡量。

如果几乎所有人都在宽容丰富的长端失败,那么为了你在无情的干旱短端生存,这本书必须有意地与众不同。这本书将带你走上一条少有人走的道路。你可能会对其中的某些部分持有异议,但你会以改变的方式走出来。例如,和你之前的所有人一样,你会得出结论,挑选个股是破产的。你也会亲眼看到投资过程中究竟在哪里创造了财富。

摘要

在本章中,我们为本书的其余部分设定了背景。股票市场既不是艺术形式,也不是科学。市场巫师既不是天生的,也不需要极度聪明。他们是在逆境的熔炉中锻造出来的。股票市场是一个无限、复杂、随机的游戏。赢得这场游戏的唯一方法是留在其中,通过调整你的策略以适应市场的无限、复杂和随机的特性,并相应地挑选股票和削减损失。在接下来的章节中,我们将考虑如何将卖空纳入你的交易策略,并实施技术以提高你的成功率和盈利预期。

市场参与者通常比买入持仓更不愿意卖空。这归因于一些技术因素,也因为人们对卖空的普遍恐惧,这种恐惧是由与卖空相关的许多神话所传播的。我们将在下一章讨论并驳斥这些神话。

第二章:10 个关于卖空的经典神话

自从 1975 年的电影 《大白鲨》,每当我们进入水中,我们都会对游弋在水下的生物有一种本能的恐惧。鲨鱼是无与伦比的杀戮机器。它们拥有比最先进的声纳还要好的检测系统。它们比快艇游得更快。它们有三排锋利的牙齿,不断地再生。然而,你是否知道在你舒适的家中的某个阴暗处,有着比任何大白鲨都要致命一千倍的东西?*均每年有 80 次鲨鱼袭击,大多数是探索性咬和误认身份。与此同时,从床上摔下来的概率要大得多。鲨鱼是雄伟的生物。如果它们想要我们死,我们早就死了。显然,它们不喜欢垃圾食品。

卖空者就像鲨鱼,稍微不那么雄伟,但仍然被误解得很厉害,而且并没有你想象中那么致命。当你的同行,在被认为是最受鄙视的行业中,一提到你的职业仍然会欣然拿起草叉时,你知道自己有点名声不佳。在这一章中,我们将揭穿围绕卖空的 10 个最持久的神话:

  • 神话 #1:卖空者毁掉养老金

  • 神话 #2:卖空者毁掉公司

  • 神话 #3:卖空者毁掉价值

  • 神话 #4:卖空者是邪恶的投机者

  • 神话 #5:卖空有无限的损失潜力,但有限的利润潜力

  • 神话 #6:卖空增加风险

  • 神话 #7:卖空增加市场波动性

  • 神话 #8:卖空导致股价崩溃

  • 神话 #9:在牛市中,卖空是不必要的

  • 神话 #10:"结构性卖空" 的神话

神话 #1:卖空者毁掉养老金

"你信仰上帝吗,雪菲先生?"

"我相信合理的回报率。"

– 《007: 皇家赌场》,詹姆斯·邦德

在 2008 年的大金融危机GFC)中,许多有影响力的人物鼓励市场参与者购买股票以“支撑市场”。他们声称这是“爱国主义的行为”。我成长于一个时代,在那个时代,爱国者是无私的个人,他们冒着生命危险,以便他人有一个更美好的未来。在华尔街某处,一个爱国者变成了一个将其他人的钱置于风险中,以保证年终奖金和自我膨胀的人。

在 2008 年的 GFC 中,卖空者并没有摧毁任何人的养老金,因为一个简单的原因:养老金基金并没有分配给卖空者。他们也没有造成 GFC。卖空者没有证券化有毒债务或导致房地产市场泡沫,也不负责其崩溃。他们的罪行是做好功课,选择另一边,并从这场惨败中获利。

交易员只做两件事。他们要么赚钱,要么找借口。当他们赚钱时,业绩说明一切。当他们没有赚钱时,他们会找借口。短头卖者是完美的替罪羊。最激烈批评短头卖者的人并不完全是基金管理的贵族。

此外,长期来看,将短头卖者归咎于自己的不幸可能会适得其反。你可以以两种方式过你的生活:作为英雄或作为受害者。英雄会承担责任,迎接挑战,并战胜逆境。受害者会责怪他人的失败。将短头卖者归咎于“爱国者”选择了受害者的道路。下次资产配置者决定他们的配置时,你认为他们更愿意分配给谁:英雄还是受害者?

现在,做空者真的会摧毁养老金吗?关于你自己的养老金最重要的问题是:“我是想靠故事退休,还是想靠数字退休?”在你退休的第二天,什么对你更重要:所有那些激动人心的投资主题还是你银行账户里的余额?

如果你认为它们是同一回事,那么继续翻腾,等待握手和金表,或者从线上经理那里得到一次改变人生的谈话。然而,如果你选择以数字退休,那么让我们来看看数字。

与主动投资和被动投资辩论相比,没有什么比“故事与数字”二分法更能说明问题。主动管理指的是基金经理将押注从基准中抽走的做法,这被称为主动资金。被动投资是指通过模仿指数来最小化跟踪误差。主动管理者声称他们的选股能力和投资组合管理技能可以提供优异的回报。然而,数字讲述了一个不同的故事。根据标普的《指数对比主动》报告,在 1 年、3 年和 5 年的时间跨度上,绝大多数主动管理者的表现都不如标普 500 指数基准。这意味着他们的累积复合回报低于基准。交易所交易基金,或ETFs,在每年的记录中表现比主动管理者更好,甚至在最严重的市场下跌期间也是如此。

关于主动管理者表现与基准比较的更详细报告可以通过标普的 SPIVA 报告获得:www.spglobal.com/spdji/en/spiva/#/reports/regions

事实就在眼前。现在证明的责任不再在于 ETFs,而在于主动管理者能否证明他们能够比指数提供更多的回报。辩论逐渐从“我们应该分配给哪个经理?”转向了“提醒我为什么我们应该选择一个昂贵的、表现不佳的基准追踪者,而不是选择一种流动性更好、更好、更便宜的替代品?”

不幸的是,还有更多。偏离基准的惩罚是严重的。如果管理者偏离并表现出色,他们被称为“股票选择者”。然而,当他们偏离并表现不佳时,他们被称为“跟踪误差高”。这经常导致赎回,对于基金经理来说是死亡之吻。当选择是成为英雄还是保住你的工作时,自我保全促使主动管理者模仿基准,这种做法被称为暗中跟踪指数。这就是著名的“没有人因持有[插入大型安全蓝筹股票名称……]而被解雇”的说法。如果主动管理者最终效仿其基准,那么“主动与被动”之争就是一个错误的名称。这实际上是在低成本指数基金与通过自我保全的主动管理者进行昂贵的暗中跟踪之间做出选择。无论哪种方式,你都会得到同样的指数,但是对于后者,你还必须支付一个中间人,即主动管理者。正如 Vanguard 的创始人约翰·博格尔曾经说过的:“在投资中,你得不到你不付钱的东西”。

这并不意味着主动管理应该死得无声无息。有些杰出的主动管理者确实物有所值。这仅仅意味着普通的主动共同基金经理给主动管理抹了黑。选择主动管理的投资者不仅承担股权风险溢价,还承担主动管理风险溢价。当前主动管理的危机只不过是每个行业中那些意识到自己再也不能拖延效率的中间人的一贯做法。

接下来,让我们看看熊市时会发生什么。市场的*均回报率在 6.3%到 8%之间。一个世纪的复利回报是天文数字。所以理论上来说,你应该长期投资。再向那些在 2001 年和 2009 年退休的人群解释一遍。在一个十年内市场曾两次下跌 50%。当对“太大而无法失败”和“杠杆过度”的回应是使它们变得更大、超级杠杆,并将同样的人放回金融危机时期的位置时,可以放心地说市场肯定会再次陷入“困境”。在熊市期间,仅持有多头头寸的主动管理者可能会展现出英勇的风采,但是当你的净资产下降了 50%时,1 或 2%的超额表现就成了一个舍入误差。十年内两次双黑坡,每个人都想要熊市保险:“熊市期间我应该买什么?”

让我们重新审视这个问题。想象有人走到你面前问:“市场正在牛市,我应该卖空什么?”停顿一秒,然后考虑一下你的反应。如果在牛市卖空毫无意义,那么为什么在熊市买入任何东西呢?没有什么安全的资产类别会神奇地上涨。在熊市唯一上涨的是相关性。一旦“掉落的刀片”的雨停下来,就会有充足的时间以白菜价购买。

在熊市中,唯一能够保证合理回报率的市场参与者是那些与指数呈负相关的人。这些人就是卖空者。你不必喜欢他们。甚至在牛市期间你也不必继续投资于他们。与其他任何市场参与者相比,他们更了解资金流入和赎回的周期性。如果你选择依靠数字退休,那么你应该考虑将资金配置给卖空者。

这给我们带来了一个违反直觉的结论。如果你选择依靠数字而不是故事退休,那么被动投资是长期的正确选择。为了在经济下行期间保护资本和创造超额收益,投资者需要将资金配置给卖空者。在主动管理领域,能够为你的养老金提供合理回报率的唯一市场参与者就是卖空者。

另一个对从业者而言违反直觉的结论是进化。主动型基金经理面临前所未有的生存危机。如果他们想要生存下去,就需要进化、适应并获得新的技能。卖空可能会是一项罕见的技能,非常适合决心保持相关性的市场参与者。

神话 #2:卖空者毁掉公司

“把通常的嫌疑犯聚集起来。”

– 《卡萨布兰卡》中的雷诺船长

当 2007 年房地产泡沫破裂时,雷曼兄弟的风险委员会和董事会中的卖空者在做什么?什么也没做。他们严格地什么都没做来防止或纠正这种情况,因为他们中没有人曾经在这些委员会上任职。在资本主义的历史上,没有任何一位卖空者曾经在他们卖空的公司的董事会上任职过。

我们可以同意,基本面在长期内推动股价。驱动力是管理的质量。马克·扎克伯格是 Facebook 背后的天才。沃伦·巴菲特将一家名叫伯克希尔哈撒韦的濒临倒闭的纺织公司转变为一个工业企业集团。杰夫·贝索斯创建了亚马逊。史蒂夫·乔布斯 2.0 是苹果复兴的建筑师。如果高层管理人员如此渴望为成功负责,那么他们也应该对失败负责。史蒂夫·乔布斯 1.0 将苹果搞垮了。凯·惠特莫尔埋葬了柯达。对于贝尔斯登、雷曼兄弟、美林和 AIG 的责任完全落在那些掌舵者的肩上。做空者并没有做出摧毁这些公司的任何错误决定。糟糕的管理会做出糟糕的决定,导致糟糕的结果,就像良好的管理会做出良好的决定,导致良好的结果一样。

没有人比史蒂夫·乔布斯在他 1995 年的《失落采访》中更好地捕捉到公司最高层发生的事情。他提到了在庄严的机构的高层管理之间的“群体思维”有时会导致一种认知偏差,称为邓宁-克鲁格效应。以柯达为例,曾经是一个标志性品牌。管理层相信他们在游戏中处于领先地位,他们可以无限期地推迟创新。当世界在前进时,他们退回到了他们的老核心技术。尽管当时很悲惨,但今天在柯达的坟墓上没有鲜花。世界,甚至被裁员的 5 万柯达员工,都已经继续前进。如今,柯达成为管理层拒绝创新的失败案例。

高层管理者喜欢围绕自己与 bozocrats、非威胁性的顺从“是人”,他们的唯一目的是向上层阶级保证他们的聪明才智,加强了对不可推翻性的致命信仰。异议被压制。创新,被标记为自相残杀,迅速被埋葬在柯达创新的石棺中。

高层管理者对自己的聪明才智如此着迷,以至于他们甚至没有意识到自己已经脱离了现实。给定足够的时间,他们过时的产品会从内部摧毁他们自己。做空者只是简单地乘着傲慢一路走向尘封的终点。

资本主义的历史就是进化的故事。在第一次世界大战期间,主要的交通方式是马匹。在第二次世界大战的第一天,世界惊恐地醒来,看到德国装甲师正在剿灭波兰骑兵。残酷的教训是进化不会留下俘虏。在两次世界大战之间的数百家汽车制造商中,只出现了少数赢家。其余的行业都倒闭了。对于每个赢家,都有无数的输家。今天,每个人都对在中央公园附*跑马车感到非常满意,但没有人为已经消亡的马车工业流泪。每个人都忘记了所有那些小汽车制造商的名字。世界已经继续前进。

我们经常把标普 500 指数看作是这个具有企业名望和权力的整体殿堂,但我们忘记了自从该指数于 1957 年成立以来,只有 86 家原始的 500 家成分公司仍在指数中。其他 414 家要么破产了,要么被并入了更大的公司。Radio Shack 并不是因为卖空者而破产的。它破产是因为无法适应亚马逊和百思买等竞争对手的竞争。卖空者不会摧毁公司。他们只是在不可阻挡的演变过程中护送过时的东西离开。

神话#3:卖空者摧毁价值

"价格是你付出的,价值是你得到的。"

– 沃伦·巴菲特

市场评论员喜欢在股价暴跌时给价值毁灭贴上一个美元的标签。2018 年 7 月 26 日,扎克伯格先生的净资产缩水了 120 亿美元。由于卖空者有望从跌价中获利,他们因附带关系而被指控破坏价值。例如,乔治·索罗斯经常与 1995 年英镑贬值联系在一起。一个人如何能独自拉低地球上最富有国家之一的货币?他大胆押注于英格兰银行不可持续的立场。

这的核心是对内在价值和市场价值的混淆。一个是价值,另一个是估值。内在价值是公司通过产品和服务销售创造的净财富。市场价值是市场参与者愿意支付的价格。市场价值和内在价值生活在很少交汇的*行宇宙中。一个是辛勤的工作。另一个是传说中的凯恩斯式选美大赛。最终结果是股东不会创造比卖空者摧毁的价值更多的价值。

神话#4:卖空者是邪恶的投机者

"我很温柔,我很可爱。但我真正想做的是伸手进去,把他们的心撕出来,在他们死之前吃掉。"

– 坠入神坛的天使,关于卖空者的话

人们经常忘记,当史蒂夫·乔布斯重回舵手时,这个标志性的标志再次被放在了杂志封面上。亚马逊并不总是华尔街的宠儿。现在被认为是有远见的管理,很长一段时间都被认为是对股东的顽固不尊重。

当高管抱怨卖空者及其代理传播的恶毒谣言时,他们忘记了史蒂夫·乔布斯和杰夫·贝佐斯多年来不得不忍受同样的恶毒。他们提出了对抗卖空者的最佳解药。制造畅销产品,妥善管理公司,卖空者就会消失。今天,没有卖空者会对苹果出手。给所有 CEO 的忠告,对抗卖空者的疫苗是:将公司的利益、员工、客户、环境、股东和管理层的利益排在首位,一切都会好起来。

如果你的方法是从研发、客户服务中挖空资源,随机“重组”人员,并将组织图扁*化,从事激进的会计实践,并为董事会投票支持荒谬的股票期权计划,吞并无用的收购,并且,最重要的是,为股票回购计划提供资金,那么,终有一天,彩虹的另一边将有一锅黄金可供做空者分享。

2007 年,量化研究全球负责人马修·罗斯曼发表了一份关于量化交易员灭亡的说明,这篇说明后来成为雷曼兄弟历史上流传最广的研究成果。随着做空者与雷曼之间的斗争升级,他向高管展示了一份欧文·拉蒙特的白皮书,标题为Go Down Fighting: Short Sellers vs. Firms。理查德·富尔德并不感到高兴。他责怪做空者散布恶意谣言,导致了雷曼的股价下跌。十年后,尘埃落定。关于全球金融危机和银行家傲慢的其他文章都以理查德·富尔德在众议院委员会作证的图片为插图。成为全球金融危机的标志性人物是一种粗暴的历史方式,即使是按照冷酷的投资银行家的标准。我为富尔德先生感到难过...

欧文·A·拉蒙特的Go Down Fighting论文可以在此处的Oxford Academic上完整访问:academic.oup.com/raps/article/2/1/1/1563177

但是,如果导致公司、市场和货币崩溃的仅仅是口臭、多彩的语言和相对于总体浮动的小头寸,那么对资本主义的信心应该加入大白鲨和北极熊的濒危物种名单。做空者的国家运动是揭示企业时空连续体中的悖论。无知和能力不能同时存在于同一地方。基本上,如果你不知道发生了什么,就不能假装知道自己在做什么。奇怪的是,这是被困扰的首席执行官希望我们相信的谎言。每当他们被问及下属的非法活动时,他们的首要防线就是装作愤怒,把他们扔到贝宁哲·巴尔斯下面,假装他们不知道一些孤立的流氓个体所犯的非法行为。这是值得赞扬的,除了全世界的每个人都知道钱不是长在树上的。金钱留下踪迹。奖金不是慈善捐款。

此外,公司规模也不是一个有效的借口。例如,战争是肮脏的生意。将军们常常远离作战地域。然而,这并不意味着他们的最低级士兵可以肆意抢劫和掠夺而不受惩罚。所以,当 CEO 声称他们不知道下属所犯的欺诈行为时,要么他们是故意视而不见,因此参与了掩盖,要么他们真的不知道发生了什么,因此无能。无论哪种情况,他们都不适合担任职务,也不配得到他们的报酬计划。这解释了为什么每当卖空者揭露不端行为时,高层管理人员都会采取进攻性行动,并将卖空者描绘成传播恶意未经证实谣言的邪恶投机者。没有什么可担心的公司可能不会开心,但他们很少在卖空者身上浪费时间进行法律诉讼。

卖空者就是市场上的蝉。从来没有人因为蝉声宣告夏日结束而责怪过蝉。当卖空者出现时,这可能预示着好时光的结束。他们不只是空谈。他们言出必行。如果有人愿意冒资本风险,持有者最起码应该重新审视他们的看涨立场。卖空者经常被指责散布恶毒谣言并从下跌中获利。公司会请买入评级的分析师吃饭,却将卖空者告上法庭。因此,卖空者必须对他们的事实和措辞小心谨慎。其次,监管机构不会善待卖空者在养老基金的大额持股上的卖空行为。它们定期接受审计。合规是一种生存机制。如果你的商业模式是通过散布谣言操纵股价并据此交易,那么放下这本书去买咖啡杯,因为“联邦人”即将在你的会议室设立基地营地。

“如果我们在与罗马人的下一场战斗中获胜,我们将彻底毁灭。”

– 普鲁塔克关于皮尔胡斯

给卖空者的一句警告。卖空是行业中不成熟而脆弱的一环。一方面,卖空者希望得到他们为市场带来的价值的认可。用 James Surowiecki 的话来说,他们*衡了“华尔街固有的看涨偏见”,并发挥了“揭露不端行为的关键作用”。卖空者也希望得到公*对待,就像任何其他市场参与者一样。

上述引述摘自 James Surowiecki 于 2015 年在《纽约客》发表的一篇文章,链接如下:www.newyorker.com/magazine/2015/03/23/in-praise-of-short-sellers

然而,另一方面,空头卖家之所以被视为敌人,是有充分理由的。播放商业广告或赞助纪录片揭露公司的欺诈行为以及他们的管理人员是一把双刃剑。每次成功的行动都在公司、监管机构和公众之间积聚了怨恨。每一次短期的皮耶里克小冲突的胜利都使长期的胜利更加难以实现。许多司法管辖区仍然禁止空头卖出。允许空头卖出的那些地方有繁琐的行政规定,例如上涨规则,交易前必须确保“借入”股票。上涨规则规定,空头卖出只能在交易价格上涨后进行。

尊重永远不是理所当然的,而是始终需要赢得的。只要空头卖家采取肮脏手段,他们就应该被同等鄙视对待。最有力的激励可能是投资者的态度。空头卖家拥有如此硫磺般的声誉,以至于许多投资者将简单地拒绝向空头卖家分配资金。

本书的前提是,空头卖出不必是冲突的。请对高级管理人员友善。不要提醒他们已经过时。时间和市场已经够残酷了。中间地带就是说你在相对基准的表现不佳的股票上空头。寻找相对空头并不会激怒公司,事实上恰恰相反。硅谷的每位初创企业家都知道市场只有两个季节,牛市和熊市。牛市是 A 轮和 IPO 的季节。熊市是“回到为人工作”的季节。防御性行业的高管,如食品或公用事业,不指望他们的股票在牛市中成为首选资产。事实上,他们可能会撤销给那些在牛市中大举购买他们股票的经理的养老金授权,除非你是沃伦·巴菲特并且你与可口可乐交谈。

神话 #5:空头卖出的损失潜力无限,但利润潜力有限

"直到教训消失,一切都不算失去。"

– 特蕾莎修女

股价可能会多次上涨,但只能下跌 100%。因此,空头卖家使自己面临无限的损失和有限的利润。每位基金经理都有一个不那么秘密的梦想,那就是把自己的名字传承下去。只是坐着看着自己的空头多次上涨的“经理”应该让这个梦想成真。他们有资格在一个公共厕所的底部得到他们的名字的权利... 没有什么借口可以为糟糕的风险管理辩解。

另一方面,让我们来认识一下乔·坎贝尔(Joe Campbell),一个年轻有活力的企业家,业余时间是投资者。 2015 年 11 月 18 日,他以*均每股$2 的价格把卡罗比奥斯(Kalobios,简称 KBIO)做空,总市值为$33,000。 之后出现了制药巨头马丁·施克雷利(Martin Shkreli)拥有卡罗比奥斯 50%股权的消息。 市场闭市后,股价飙升了 800%。 借贷一夜之间消失了。 无法满足保证金要求,不幸的空头卖家在 GoFundMe 上发起了众筹活动,希望得到其他交易者的同情,但却面临着市场参与者“复仇交易”和恶毒评论的双重打击。 我对坎贝尔先生表示同情,愿他的故事至少能成为渴望做空者的一则教训:

  • 低价股是旅游陷阱。 游客不关心借贷的质量。 他们对故事感到兴奋。 当召回发生时,他们争相定位。 当没有借贷可用时,他们被迫*仓,最终演变成了空头挤压。

  • 低价股是二元事件。 要么它们归零,要么有公司行动,股价飙升。 低价股是高风险、低回报的交易。 在挑战布鲁斯·李之前,先在你的黑带上多积累一些经验。 90%的市场参与者是无法盈利的。 剩下的 10%中,大多数人仍然不做空。

如果坎贝尔先生感到慰藉,那么对于施药者来说,他已经成为一名被定罪的重罪犯。

神话#6:做空增加了风险

“事实并不因为被忽略而停止存在。”

– 奥尔德斯·赫胥黎

做空是有风险的。 然而,不知道如何做空的风险要高得多。 当市场参与者选择不学习这门手艺时,并非他们不愿冒险。 他们保守到寻求风险的程度。 把它想象成紧急演练。 拒绝练习演练并不会让火灾、海啸或地震的风险消失。 人们选择在罕见但危及生命的事件发生时毫无准备地过日子。 成为市场参与者不仅仅是买进并期待顺利。 事情可能会变得艰难,而且将会变得艰难。

在潜意识水*上,每个市场参与者都对即将到来的熊市心存恐惧。 他们知道他们会失去一些收益。 他们的最佳情况是在熊市来临之前卖出并等待。 这有时会促使他们过早卖出并错过大的波动。 正如彼得·林奇所说:“投资者为了纠正或预测纠正而准备所失去的钱比纠正本身失去的钱要多得多。”

由于任何学术研究都无法说明这一点,让我们内省一下,玩一个游戏。拿两张纸,画两栏。在第一张纸上,写下你对熊市的恐惧。你的收益、投资组合、净值和工作会发生什么?你如何准备?具体说明它何时以及如何在你的日常工作中显现。例如,你是否经常检查市场?你是否扫描新闻以寻找潜在的熊市催化剂?你是否过于保守还是认为可以冒险?

接下来,想象一下你对在熊市中赚钱的能力非常淡定,以至于随便说:“牛市。熊市。它们都尝起来像鸡。”你会做些什么不同?你会持有头寸更长时间吗?你会调整头寸大小吗?你会一直检查新闻吗?将所有的感受写在第二张纸上。完成后,拿起第一张纸,逐个解决右栏中的所有恐惧。你的恐惧中大约有一半是情绪吸血鬼,它们会消耗你的能量。在逻辑审查的光下,它们会消散。

在内心深处,我们都知道,无法做空比根本不做空更加危险,因为它使你能够从牛市和熊市中获利。

神话#7:做空增加了市场波动性

2008 年,银行高管们站在他们办公室的窗台上凝视深渊。银行业游说团迅速走向华盛顿,要求暂停做空交易。作为回应,美国证券交易委员会(SEC)在该国暂时禁止了做空交易,以“恢复市场*衡”。这一禁令后来被解除。在尘埃落定后,对做空交易禁令的影响进行了一些分析,美联储发布了一份报告,其中他们得出结论,做空实际上减少了波动性。

在被称为股票市场的拳击场上,美联储不会每天都站在做空者一边。毫不拖泥带水,看看他们报告的开篇段落:

“为了应对 2008 年秋季金融股价格的急剧下跌,一些国家的监管机构禁止了特定股票和行业的做空交易。证据表明,这些禁令几乎没有阻止股价下跌,但显著增加了流动性的成本。2011 年 8 月,美国市场经历了一次大幅下跌,当时标准普尔宣布降低了美国债务的评级。我们的横断面测试表明,股价下跌并不是由做空交易显著推动或放大的。做空似乎并不是最*股市下跌的根本原因。此外,禁止做空似乎不能阻止股价在特定公司或全球经济基本面疲软时下跌,并可能对市场参与者施加高昂的成本。”

报告标题如下:《纽约联邦储备银行,市场下跌:禁止做空的成果是什么?,罗伯特·巴塔利奥,哈米德·梅赫兰,保罗·舒尔茨,第 18 卷,第 5 号,2012 年。

市场参与者做空有各种各样的原因。期权交易员、可转债经理和指数跟踪者需要对其头寸进行对冲。无法做空会减少流动性和金融产品的供应。对做空的限制因此是市场不成熟的标志。

神话#8:做空会导致股价崩溃

做空者根本没有足够的火力来击垮股价。做空者需要借股才能卖空。这些股份来自愿意将部分持股借给股票贷款部门的股东。借股可用性通常*均不到流通股的 10%,换句话说,是公共投资者可用的股份部分。这意味着做空者只代表了整体卖出量的一部分。

做空者的 BB 枪可能会对市场产生短期影响,但真正的伤害是由机构投资者卖出的重型火炮造成的。这让我们对做空有了一个有趣的看法。在空头上赚钱不是关于发现潜在下跌的股票。这是关于乘坐机构投资者清仓的尾巴。

神话#9:牛市中不需要做空

“修补屋顶的最佳时机是在太阳照耀的时候。”

– 约翰·F·肯尼迪

一些市场参与者不想在牛市中做空。他们对“好的做空想法”的稀缺感到惋惜。此外,他们不想通过做空股票浪费宝贵的α值来追赶竞争对手。他们拖延着磨刀霍霍,直到生锈为止。

没有牛市曾经提高过任何人的智商。市场参与者在牛市中不会变聪明;他们变得自满。就像等待第一次心脏病发作才开始健身不健康一样,等待熊市学习卖空是一种不专业的管理他人资金的方式。卖空是一种不使用时会萎缩的肌肉。

投资者将资金留在多空基金中的原因是下行风险保护。在牛市中,只要他们知道在熊市中有下行风险保护,投资者将原谅中等表现并容忍高费用。

贝塔赛骑手相信,当整个市场转为熊市时,会有充足的时间进行卖空。毕竟,卖空的外在游戏、工具和技术可能比多头稍微复杂一点,但这不是火箭科学。卖空首先是一种内在的游戏。不要低估内化卖空的心理纪律所需的时间。

开始的错误时间是当多头亏损,投资者在你的脖子上喘气的时候。

神话#10:"结构性空头"的神话

"伴随着巨大的力量而来的是巨大的责任。"

– 蜘蛛侠的本叔

结构性空头是被视为不可逆转地注定失败的股票;就像 20 世纪 30 年代的马车、数字时代的印刷报纸和可再生能源时代的煤矿一样。它们被认为是强制性的空头,因为它们的商业模式或行业的动态结构上存在缺陷。

结构性空头就像市场大师在媒体上滔滔不绝一样廉价,成千上万。盈利性的结构性空头是金融服务行业的独角兽,像市场巫师一样稀有且难以捉摸。

第三章中,走进狂野的空头,我们揭穿了结构性空头的神话。现在,让我们专注于管理他人资金时寻找结构性空头意味着什么。市场参与者一直坚信,在某个地方,有一只股票他们只需卖空并扔掉钥匙。因为它将自己走向破产,所以不需要任何进一步的维护。

现在,他们并不对他们的多头持有相互信念。当然,他们相信他们需要持续维护。他们相信与管理层会面,更新盈利模型,与分析师通话等等。因此,他们相信在多头方面有严格的职业道德,而在空头方面则被动。在现实世界中,每个人都知道空头比多头要困难得多。那么,为什么在困难的一面,漫不经心的懒散会奏效,而辛勤的工作在容易的一面几乎得不到回报呢?

当人们公开持有这种不对称的不受质疑的信念时,令人不便的事实是,他们对于短空头并没有多加思考。他们不知道如何做空。显然,他们也没有尝试很努力。如果他们有尝试,现实很快就会打败他们。然而,他们依然希望事情会奇迹般地自行解决。他们自信地市场推广他们没有掌握的技能,乐意接受他人的钱并收取丰厚的费用。然而,他们并不打算为必然的不适负责。用英国女王的英语来说,这被称为失职。在交易员的执行英语中,这些个体被称为小丑。在本书的其余部分,让我们将他们的地位装饰成货币小丑声chremato: 货币,coulro: 小丑,phones: 声音)。

摘要

做空已经长期存在于我们的门口的未知领域。与现代技术,如人工智能或机器学习相关的书籍和白皮书比起,关于做空的出版物更多,而做空已经存在了几个世纪。如果我们想要给这项技术一个尊贵的称号,重建这门学科,并吸引有才华的人才,驱散谬论尤为重要。

在下一章中,我们将讨论空头市场的市场动态,并解释对这些动态的深入理解对于成功至关重要。

第三章:走进狂野的做空面

“在理论上,理论和实践是一样的。在实践中,它们是不同的。”

– 约基·贝拉,《洋基哲学家》

对于许多仅做多的参与者来说,卖空是一个秘密的幻想。他们都曾经碰到过一些他们分析过的股票,得出结论认为它注定会失败,并希望自己能做空它。然后,他们看着它坠落。他们相信自己的分析超能力在做空方面也会奏效。在理论上一切都很顺利,直到它必须在实践中奏效为止。当市场参与者来到做空的世界时,他们认为他们应该简单地做与在做多方面相反的事情。

在这一章中,我们将从做多方过渡到做空方的旅程。我们考虑为什么大多数交易者认为他们可以做空却在实践中失败。首先,我们将研究为什么基于估值的卖空会失败。然后,我们将彻底揭穿结构性卖空旅游陷阱。我们将在学会无助的炼狱中徘徊,然后醒悟到做空的现实。在本章的第二部分,我们将开始深入探讨做空和其独特的特点。

在此过程中,我们将涵盖以下主题:

  • 依据加普的做多方世界

  • 结构性卖空:金融服务行业的独角兽

  • 克服学会无助

  • 金钱“是”在“应该”发生的事件之间赚到的

  • 做空面临的独特挑战

依据加普的做多方世界

“他希望他能安排一次伤害作为一种道德教训。”

– 约翰·欧文,《依据加普的世界》

在做多方面,市场参与者经常寻找长期前景良好但暂时定价错误的股票。他们想要买一些以折扣价增长的东西,就是著名的“安全边际”。这种方法被称为以合理价格增长GARP)。如果在做多方面这种方法看起来运作良好,那么在做空方面做相反的事情就可以了,没错吧?这甚至听起来可能像以记录价格潜水DARP)。

第一个逻辑步骤是最简单的:找到价格超现实的股票。总有一支股票,有时是整个行业,似乎违反传统的重力法则。随着全球货币当局在“打印”按钮上打盹,荒谬定价的股票层出不穷。第二步是对奇特的商业模式、增长率的可持续性、现金流耗尽速度等进行分析。一旦星星排成一列,你发现悬浮的估值与下沉的商业模式相结合,就是时候用一些精心设计的做空头寸教训那些傲慢的股票了。过了某个阶段,无论商业模式有多好,估值都不再有意义,事情应该回归到合理价位。

尽管这种方法表面上似乎合乎逻辑,让我们考虑一下为什么可能不是这样。GARP 的概念隐含地依赖于公*。廉价的估值会回归到公*。目标是在股票便宜时抓住它们,并在修正行情上赚取利润。对于技术娴熟的市场参与者来说,买入大幅超卖的股票,然后等待反弹是公*且合乎逻辑的。因此,假设不可持续的定价会回归到公*估值是公*和合乎逻辑的。问题在于,将这种对公*的潜意识信仰带入短期世界证明是一个致命的优点。

达到同温层估值的股票往往具有足够的动量将它们推向电离层,然后引力将它们拉回。拥有 100 倍市盈率PE)(一种估值指标,计算方法是股价除以每股收益)的股票已经逃脱了理性的引力。它们也许会涨到 150、200 或 3000。

香槟股票在泡沫区域仍然有泡沫,这时,华尔街的欢呼者方便地推出同样的套路:“永久的高原”,“这一次不同”,“范式转变”,“新经济”。市场参与者可能把自己视为疯狂人群中的理性声音。然而,正如西尼加,投行家白天的守护神,夜晚的斯多亚哲学家所证明的,一颗理智的头脑对抗疯狂的人群仍然是不公*的战斗。

在几何上升之后,股价出现了抛物线式的“大结局”上涨。这时,基本面空头卖家遭受了理性的诅咒:他们提前离场,因为仓位是不可持续的。我们都经历过这种情况。我们买回我们的空头仓位,收盘最后的高点,然后恼怒地离开,只是发现牛顿物理定律不区分水果、热核洲际弹道导弹和伊卡洛斯股票。

故事的寓意:卖空一只毫无道理的股票也没有道理。正如凯恩斯曾经说过的那样,“市场的非理性可能比我们的偿付能力更长久。”

结构性空头:金融服务行业的独角兽

“如果你想要保证,就买一个烤面包机。”

– 克林特·伊斯特伍德

一旦市场参与者在试图融化伊卡洛斯股票的翅膀上多次受挫后,他们会改变策略。他们渴望确定性。他们寻找那些已经符合所有“坏”标准的股票:坏公司、坏行业、坏产品、坏管理、坏估值、坏消息传播、坏评级等等。他们开始寻找结构性空头。幸运的是,失败之路上的公司远比成功之路上的公司多得多。

问题在于时机。每一点信息都附带着一个价格标签。这被折价在股价中。到了做空者积累足够证据可以毫无疑问地得出他们遇到了结构性空头的结论的时候,机构长期持有者已经离场了。剩下的唯一股东是稳定的长期投资者,如创始人和战略合作伙伴。做空“结构性空头”变成了一个二元事件。要么它们破产,要么发生一项重大的公司并购或收购事件。简单来说,股价要么下跌到零,要么保持不变。

此外,做空比买多复杂一些。做空者需要卖出他们根本不拥有的股票。因此,他们方便地从股票借出台中借来,这些台中收取借贷费用。借贷费用是供求关系的直接函数。对于难以找到的问题,借贷费用从一般抵押品的 0.25%-0.5%上涨到两位数。结构性做空恰好也被称为拥挤做空,这种做空的借贷费用会让莎士比亚的夏洛克嫉妒。股价可能会下跌,但借款成本非常昂贵,任何一点买压都会引发恶性做空压力,你可能会发现自己在两个月内赚了 1-2%,但股价在 3 天内上涨了 15%。

结构性做空是廉价的,就像市场大师一样:千篇一律。盈利性的结构性做空就像市场巫师一样:金融服务的独角兽,证明了没有规则的例外。

克服学会的无助感

“记住,除非他感到气馁,否则没有人真正被击败。”

  • 中国裔美国哲学家布鲁斯·李

经过几次试图捕捉射击星星和咀嚼干骨头的失败尝试后,市场参与者在财务和情感上陷入了困境。然而,任何精心制定的作战计划都无法在第一次遭遇敌人时生存下来。做空一方变成了一个无尽的挫折源,其逻辑违背了逻辑。

狗是人类最好的朋友,但不幸的是也是他最喜欢的实验室测试对象之一。在一次著名的实验中,积极心理学运动的先驱马丁·塞利格曼剥夺了狗们获得奖励的机会。奖励分配的随机性进一步剥夺了实验狗的希望。它们逐渐变得冷漠。即使他们有明显的成功机会,他们也停止了努力。他们只是放弃了“免费赚钱”的交易。这些狗已经学会了无助感。

在金融狼群中学会的无助的症状表现为一些象征性的空头,大量的空头指数期货和结构上的高净头寸。在执行交易员的英语中,他们放弃了试图做空特定股票的尝试。他们只保留零星的象征性空头想法。他们通过出售期货对冲或*衡多头和空头。从多头席位上观看比赛时看起来很容易,但现在他们在实地上被打了几次后,这似乎是不可逾越的困难。

沮丧的市场参与者随后退回到他们的舒适区:多头。这甚至在他们的营销材料中也发生了。他们仍然谈论下行保护,但他们向投资者宣传的精明股票几乎都是多头方面的。

在这一点上,他们无意中背叛了他们作为多空交易者的唯一"理由":他们能够在市场的情绪化波动中产生阿尔法。判断市场参与者是否是认真的空头卖家的一个快速方法是查看他们在营销材料中发布的空头和多头观点的比率。

幸运的是,学会的无助是可以逆转的。这就是这本书的一部分。

金钱"是"在"应该"发生的事件之间赚取的。

"大多数决策可能应该在你希望拥有的信息的大约 70%左右做出。"

  • 杰夫·贝索斯

空头交易的现实是,金钱是在"应该"发生的事件之间的时间内赚取的。让我解释一下我的意思。当股票达到不可持续的水*时,它们"应该"下跌。当公司处于完全混乱状态时,它们"应该"倒闭。在轨道上的老卫星一样的灭亡的致命时刻和僵尸股票的苦闷炼狱之间,它们并不是由市场的某个斯科蒂奇神奇地传送下来的。在它们"应该"下跌的时间和它们"应该"破产的时间之间,事实上,它们确实在很长一段时间内下降了很多,不为人注意,不受欢迎,但对一些精明的空头卖家来说,仍然是非常有利可图的方式。

他们退出了对话。它们在整个过程中的估值并不奢侈,事实上恰恰相反。它们与同行和整个市场的估值相当,甚至稍微便宜一些,但它们之所以便宜是有原因的。它们让人失望。机构逐渐出售了它们的持股。零售商忙于追逐新的热门股票。市场参与者没有理由再持有它们了。它们在市场选美大赛中犯下了终极罪行:它们无聊。

仔细想想:在多头方面,你不会拥有一只无聊的股票。其他不太有才华的市场参与者可能最终会得出同样的结论。他们要么卖掉,要么远离。不吸引人的股票不会表现出色。随着时间的推移,小的表现不佳会累积成大的失望。简言之,你在多头方面不想拥有的股票是空头账本的潜在候选人。

找到好的空头的关键在于接受一个反直觉的真理:它并不令人兴奋。好的空头是无聊的。它们既不显得过于昂贵,也不显得太有缺陷,它们的估值往往与同行相似。它们只是无聊的表现不佳者。

空头面临的独特挑战

“当事情出错时,不要跟着一起出错。”

– 猫王

人们在做空交易上失败,是因为他们忽视了三个对他们不利的关键因素:市场动态、稀缺心态和信息的不对称性。

市场动态:做空不是股票挑选比赛,而是头寸规模化练习

“这是太空,环境不合作。”

–《火星救援》

成功的多头扩大。成功的空头缩小。在多头方面,市场做了大部分的工作。在空头方面,市场并不合作。失败的空头膨胀,而成功的空头收缩。

为了说明这一点,让我们看看下面的表格。想象一下我们有四只股票:两只多头(A 和 B)和两只空头(C 和 D)。这里的目标是说明多头和空头的行为有所不同。为了保持简单,让我们从价格为 100 美元的 4 只股票开始。开放的多头市值为+$200,空头市值为-$200。总暴露(多头和空头账簿的绝对值)为 400 美元,总净暴露(多头和空头账簿之间的差异)为 0 美元。在金融术语中,净暴露低于 10%通常被分类为市场中性。这听起来可能更聪明、更安全,但绝对不是无风险。

100 天后,A、B、C 和 D 的价值分别为 110、95、90 和 105。

代码 第 1 天 第 100 天 盈亏
A 100 110 10
B 100 95 -5
市值多头 200 205 5
C -100 -90 10
D -100 -105 -5
市值空头 -200 -195 5
总暴露 400 400 10
净暴露 0 10 10

总暴露仍然是 400 美元,但净暴露现在是+10 美元。在多头方面,有更多有效的东西,不起作用的东西少了。然而,在空头方面,有效的东西少了,不起作用的东西多了。尽管每个做空股票(C 和 D)的绝对移动等于多头头寸(A 和 B)的绝对移动,但净暴露自然上升。成功的多头扩大,空头缩小。这导致净暴露的自然健康向上漂移。这意味着多头和空头的暴露不匹配。

股票通常按部门、行业和子行业分类。市场参与者倾向于在类似的部门购物以进行对冲。例如,可能是丰田对通用汽车。部门暴露也会出现错位。在多头方面,有助于增加规模的部门。与此同时,在空头方面,造成伤害的部门规模增加。

Beta 是对市场的敏感性。在高中令人昏昏欲睡的数学课上,这是一支股票的离散收益与其基准的协方差矩阵。在执行交易员的语境中,这是当指数波动时股票波动的程度。在考虑 Beta 时情况变得更糟。做多方从扩张中受益,但做空方面却经历了来自收缩的净拖累。最重要的是,在做空方面,市场不合作。

任何一个清醒的学者都会逻辑地认为,解决方案是增加命中率和超额的做空头寸。如果市场参与者 100%正确,那么做空头寸可以超额。在现实世界中,任何被打击和受伤的做空从业者都会哭着说疯了。增加命中率意味着成为更好的股票选择者。这是每个人每天都在努力实现的目标。问题在于,即使投资传奇人物在做多方面的胜率也仅在 30%到 50%之间,在做空方面也只能达到 20%到 40%之间。因此,解决方案就是做更多相同的事情,并期待不同的结果。欢迎来到疯狂边际贡献的世界。

好吧,既然几率更低,做空的扶手椅战略家会继续争辩说,解决方案显然是将仓位大小缩小以控制损失。问题再次出在市场动态上。成功的做空者缩小。例如,进行-0.50%的赌注意味着-10%的下跌将产生+0.05%的利润,这几乎不是能吸引投资者投入大笔资金的回报。

赤裸的事实是做空并不是一场选股比赛。这是一种仓位规模的练习。困难在于确定仓位大小,使其在发挥作用时起到贡献作用,但在不起作用时不损害业绩。

由于做多和做空具有相反的动态,只有两种*衡净敞口的方式:

  • 补充赢家:这是“骑赢家,割失败者”的做空版本。成功的做空需要定期补充。

  • 保持比做多多的做空头寸:在做空方面进行想法生成是大多数市场参与者的一大障碍。

这引出了下一个问题。

稀缺心态

“它在任何地图上都没有标注;真正的地方从不会有。”

– 赫尔曼·梅尔维尔,《白鲸》

需要持续提供想法的需求导致了第二个不利于做空者的因素:稀缺心态。以基本的长期持有视角对待做空的市场参与者倾向于仔细研究和挑选股票。这意味着他们的优质选择往往少而又少。长市场参与者倾向于成为捕鲸者。这在做多方面是有效的,因为成功的做多会随着时间扩展。然而,将这种捕鲸心态带到做空方面,它就变成了一场疯狂的独角鲸追逐。

卖空方需要不同的心态。它需要一种丰富心态,其中数量胜过质量。如果长期投资者是捕鲸者,卖空者就需要成为沙丁鱼渔民。沙丁鱼捕捞可能不是古典小说最具启发性的素材,但至少它能让人们有饭吃 —— 祝你好运,从北极圈带回那些难以捉摸的独角兽鲸中的一只。卖空者需要避免过滤过多。他们需要让进入投资组合变得容易,而让留下来变得困难。关键是期望每个卖空头寸都失败。

这使我们进入了第三个挑战。关于卖空候选人的信息不多。

信息的不对称

“当一个人的工资取决于他不理解某件事时,要让他理解某件事是困难的。”

– 奥普顿·辛克莱尔

除了扭曲的市场动态驱动需要稳定提供新想法之外,卖空者还面临信息有限的挑战。无论公司还是街道都没有动机主动提供可能对股价产生不利影响的信息。卖空者自食其力。

股票期权和透明度

“利润是甜蜜的,即使它来自欺骗。”

– 索福克勒斯

股票期权是吸引、激励和留住人才的一种常用方式。当公司高管的报酬直接与股价表现挂钩时,没有动机主动提供可能动摇船只的信息。卖空者面临三种困难:

  • 公司有权拒绝向公开宣称为卖空者的人提供企业准入。他们没有义务回答投资者的棘手问题。这种沉默是一种完全可以理解的人类行为,特别是当卖空者是对抗性的时候。

  • 其次,高层管理有时对卖空者采取敌对态度。好消息是,当管理层对付卖空者的皮肤足够薄到诉诸法庭时,他们在商业实践和会计政策方面通常也很激进。

  • 第三,透明度是单向的。公司对其成就大肆宣扬,但对失败则守口如瓶。当涉及成功时,公关没有预算冻结,但失败时则像永久冻土一样冰封。公开自我折磨是为了烈士,而不是为了企业战士。

在实践中,这意味着需要两倍的努力来收集一半的信息,以使投资决策变得两倍冒险。

卖方分析师是金融星系的守护者

“我是格鲁特。”

– 格鲁特,《银河护卫队》

金融是唯一一项竞争激烈的运动,啦啦队员穿着细条纹西装。卖方行业缺乏满足卖空者需求的能力。在分析师的辩护中,当整个投资银行的奖金池取决于以任何必要手段证明“买入”建议时,支持“卖出”建议是困难的。

卖方分析师没有鼓励卖出或做空的动机。公司通过发行股票、商业票据和债务等工具在资本市场上融资。他们可能会对将下一章节定为 11 或 13 的店铺的住宿爱因斯坦的人感到稍微不感兴趣。

分析师致力于与高层管理接*。买方社区会以他们促进公司接触高层管理的能力来奖励他们。正如詹姆斯·蒙蒂尔曾经说过的那样,他们是受人尊敬的秘书。因此,没有动机用卖出评级疏远管理层。当每个人都自豪地持有“买入”评级时,通过具有卖出评级的分析师发送公司请求很少会让管理层有友好的倾向。这是一个不必要的向敌方发出的警告。

最后,分析师会疏远现有投资者。谁说机构投资者从不回复卖方的电话?试着在他们的大头寸上提出“卖出”建议,他们会记住你的电话号码。

结果,卖方分析师是金融星系的守护者。更准确地说,他们是格鲁特,那个以独特一句话“我是格鲁特”而闻名的行走树木,而在这个语境中等同于“这是一次购买”。当股价表现不符时,合理化可能会非常超级派,正如对金融界所有事情都了如指掌的专家玛丽·波*斯所说的那样。因此,这是破译街头行话谜题的方法:

  • "这是一次性的,这是一次购买":股价意外下跌。我是格鲁特。

  • "由于周期性库存调整导致负增长,这是一次购买":盈利因为“软裁决”而下滑,股价表现不佳。我是格鲁特。

  • "市场是错误的,这是一次购买":股票未能随着整体市场上涨。我是格鲁特。

  • "在弱势中买入,买入低点":表现不佳持续下行。我是格鲁特。

  • "我们已经降低了我们的估计,调整了我们的目标价格,将我们的投资视野延伸到 2057 年,但保持了我们的评级,因为长期故事仍然完整,这是一次购买":表现不佳。我是格鲁特。

  • "长期投资者买入,这是一次购买":没有任何效果,价格便宜且越来越便宜。我是格鲁特。

  • "新闻流动如此糟糕,这是好消息,这是一次购买":股价跌至谷底—在那个价位,一定会有所行动。我是格鲁特。

  • "坏消息已经融入估值中,这是一次购买":没有什么发生,股价持续低迷。我是格鲁特。

  • "这是结构性空头,卖出":投资银行部门不期望在*期有任何交易。因此,烧毁那座桥是可以的。如果一支股票在一系列卖方评级下调之后仍然没有动静,那么现在就是抛售家族珍宝和大量购买的时候。

在大多数商店里仍然可以看到“卖出”建议,但这就像电梯里的“关门”按钮一样:通常是断开的,只是纯粹出于安慰性目的。

底线:这使得评级表格有点难以理解。金融克里奥尔语可能很难解读。以下是分析师评级的简单指南,它们的含义以及您应该如何做出反应:

建议 翻译 行动
强烈买入 动量股或正在筹备投资银行交易 买入
买入 默认评级 晚饭吃什么?周五看电影吗?
中性 消极意见 卖出或卖空
卖出 投降,不惧怕与公司破裂 *仓并寻找长期布局
强烈卖出 报复评级 如果最*形成了长期布局,请将家庭白银融化并买入、买入、买入,否则以市价买入
放弃覆盖 表现不佳者 在卖空前检查借入利用率

评级是固定的。坦率地说,诚信并不是那种让法拉利停放在车库里的货币。虽然分析师有保持有利评级的自然动机,但他们在数字方面享有更多自由。他们会削减其预估,延长其投资视野,并与其上涨潜力讨价还价。这是讨价还价阶段。

这是一种承认,事情可能不像预期的那样顺利。收益动能下降是卖空者中的一种流行信号。他们可能无法改变自己的评级,但他们会在数字方面更加诚实。

如果市场参与者基于分析师的估计做出投资决策,他们可能应该了解他们的预测准确性。预测似乎也不是分析师的强项。马可·迪翁,当时是摩根大通的量化研究负责人,在全球金融危机爆发前于 2007 年编制了一份卖方预测准确性报告。该论文的目的是计算分析师在一年内对其预测的准确性。

这份研究论文的结论主要解释了为什么策略着重于盈利动能,也称为随时间方向,而不是准确性。真正令人着迷的是样本内预测准确性。分析师在一年后对其盈利预测准确的概率为 2%。他们有 25%的概率相差 10%。在 2%的准确率下称为统计误差。在 25%的概率下相差 10%,即使准确性奇迹般加倍,它仍将具有硬币抛掷的长期概率。

揭开财务分析师的面纱可能会显露出有缺陷的魔术师。如果你不开心,责怪游戏,而不是玩家。分析师是才华横溢、热情洋溢、工作努力的人,对其行业和公司有着全面的了解。然而,他们运营在一个旨在促使人们交易,而不一定是为了让他们赚钱的游戏中。

摘要

市场参与者倾向于沿着可预见的路径发展,从他们自豪地踏上空头交易的未知领域的那一刻开始,到他们下意识地放弃主权的时候。最重要的是要记住,空头方不是长仓的反义词。你不能依赖错定价格的股票恢复到其公允估值,而且“结构性空头”只在空头交易旅行者的心中有利可图。空头方遵循自己的规则。

空头卖方面临的挑战之一是,长仓市场参与者不必面对的挑战,即克服信息匮乏,采取丰富心态成功地抵消扭曲的暴露。

现在我们已经驱散了一些关于空头交易的神话,并分析了空头方的特殊动态,本书的下一部分将讨论从零开始建立空头交易实践。在第二部分外部游戏:打造强大的交易优势中,我们将探讨外部游戏,或者如何发展有利的交易优势。

第三部分长/短游戏:打造长/短产品中,我们将把一切都放在一起,考虑如何建立一个投资者感兴趣的长/短投资组合。

从下一章开始,我们将讨论如何选择有效的交易方法,并开始发展你的空头交易优势。

第四章:多空方法论:绝对和相对

在本章中,我们将比较方法,特别关注绝对与相对系列。绝对系列是您可以在任何网站或*台上看到的开高低收OHLC)价格。它们通常会调整为股息、股票拆分和其他公司行动。相对系列是上述绝对系列除以基准的收盘价格,调整为货币。

我们希望展示绝对方法的弱点,以及相对弱势方法的优势,这将定义本书的方法论。在此过程中,我们将涵盖以下主题:

导入库

以下代码,实际上是本书中大部分代码,首先需要安装yfinance包:

pip install yfinance 

然后可以导入yfinance

import yfinance as yf 

在本章节和本书的其余部分,我们还将使用pandasnumpymatplotlib。因此,请记得首先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt 

多空 1.0:绝对方法

"‘但是,皇帝一点也没有穿衣服!’,一个小孩说道。

"‘倾听无辜之声!’,他的父亲叫道。"

– 阿瑟·安德森

绝对方法在直观上是有道理的:买涨的股票,卖跌的股票。来自各种提供商的数据、屏幕上的价格图表以及进入组合的内容之间存在一对一的关系。每个人都说同样的语言。投资者、市场评论员和其他各种市场参与者谈论的都是同样的价格和一般估值水*。卖出绝对价值下跌的股票会产生现金,可以用于在多头方向上购买更多的股票并增加杠杆。

只有一个小问题:产品并不总是如说明书所说那样。让我们保持冷静:绝对方法从一开始就是彻底的失败,接下来的章节将探讨其原因。

无法降低与基准的相关性

投资者明确支付溢价费用以获得不相关的回报。在执行交易员的英语中,投资者希望他们的资金增长,不受市场先生的情绪波动影响。让我们看看为什么绝对方法未能实现这一承诺。

在牛市中,潮水抬高了所有船只。很少有股票下跌,但是当它们下跌时,它们吸引了很多关注。长持有者退出股票,而空头卖家则加码。这些股票成为拥挤的空头头寸。流行的空头头寸 notoriously 难以交易——它们不流动,而且异常波动。进出这些股票会产生一些不利的市场影响,借款费用昂贵,并且它们还容易受到空头挤压的影响,即在熊市下跌结束时发生的激烈反弹。由于没有人想要通过空头挤压过度受限,这对下注规模设置了自然限制,导致空头头寸萎缩。

另一方面,在牛市中,多头头寸过度发展。这导致高结构性正净曝露,这是对市场上升方向的明确押注。在金融克里奥尔语中,这些被称为“定向对冲基金”。这些基金经理谈论对两手灵活和灵活的管理,但是一旦市场转为熊市,他们就寻求庇护在他们的书桌下的舒适之下。相反,在熊市中,很少有股票上涨。空头想法很多,但在实践中,暴露很少跨越到负区域。这意味着投资者减轻了打击,但仍然亏损。

以下图表显示了标准普尔 500 指数以及绝对价格系列中牛市或熊市的所有成分的计数。

图 4.1:在市场波动时,处于牛市或熊市领域的股票数量大幅波动

上述图表,以及与相对弱势法比较的另一个图表(我们将在“两面都提供新鲜想法的一致供应”部分回来),可以通过执行以下源代码生成:

# S&P500 dataframe: list of tickers
sp_df = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')[0]
sp_df['Symbol'] = sp_df['Symbol'].str.replace('.', '-')
bm_ticker = '^GSPC'
tickers_list = [bm_ticker] + list(sp_df['Symbol'])[:]

# Variables instantiation
window = 252
df_abs = pd.DataFrame()
batch_size = 20
loop_size = int(len(tickers_list) // batch_size) + 2

for t in range(1,loop_size): # Batch download
    m = (t - 1) * batch_size
    n = t * batch_size
    batch_list = tickers_list[m:n]
    print(batch_list,m,n)
    batch_download = yf.download(tickers= batch_list,
                                 start= '2007-01-01', end = None, 
                                 interval = "1d",group_by = 'column',
                                 auto_adjust = True, 
                                 prepost = True, treads = True, 
                                 proxy = None)['Close']
    df_abs = df_abs.join(batch_download, how='outer')

### removed for brevity: check GitHub repo for full code ###
bullbear['bulls_absolute'] = df_abs[df_abs > 0].count(axis=1) 
bullbear['bears_absolute'] = df_abs[df_abs < 0].count(axis=1) 
bullbear['bulls_relative'] = df_rel[df_rel > 0].count(axis=1) 
bullbear['bears_relative'] = df_rel[df_rel < 0].count(axis=1) 

bullbear[280:][['benchmark','bulls_absolute', 'bears_absolute', 
               ]].plot(figsize=(20,8),
                style=['k', 'g', 'r'],grid=True,secondary_y=['benchmark'],
                title = 'S&P500, 1yr High/Low count: absolute series' )

bullbear[280:][['benchmark','bulls_absolute', 'bears_absolute', 'bulls_relative', 'bears_relative']].plot(figsize=(20,8),
                style=['k', 'g', 'r','g:', 'r:'],grid=True,secondary_y=['benchmark'],
                title = 'S&P500, 1yr High/Low count: absolute & relative series') 

上述代码的结构相当紧凑和简单:

  1. 导入yfinance模块以允许从 Yahoo Finance 下载。

  2. 使用pandas.read_html方法下载最新的标准普尔 500 成分股。提取股票列表并将.替换为-以确保与 Yahoo Finance 兼容。

  3. 实例化数据框和变量以处理数据和聚合结果。使用模数//函数计算批量大小。

  4. 添加一个循环来批量下载收盘价格。使用join方法添加到df_abs中。

  5. 通过将df_abs除以bm_ticker列(使用axis=0指定)然后将其重新定位到索引的第一个值,创建df_rel

    1. 使用np.where方法定义牛市/熊市制度:如果收盘价是 252 个周期中的最高价,则分配1,如果收盘价是 252 个周期中的最低价,则分配–1;否则,分配np.nan

    2. np.nan缺失值之间传播1-1

  6. bullbear数据框上聚合结果,跨绝对和相对数据框添加水*计数(axis=1)。

  7. 绘制基准、牛市和熊市计数。

当市场上涨时,看涨股票的数量增加。当市场横盘或熊市时,看跌股票的数量增加。这表明绝对方法从定义上与市场相关。只需看看多空基金的业绩记录,就可以得出结论,绝对方法未能提供与市场不相关的吸引人回报。

接下来的几节将考虑绝对方法的一些弱点。

无法有效降低波动性

由于空头头寸比其他头寸少,*衡头寸的方法是加大更集中的头寸。这意味着一个稀释的、相对低波动性的多头投资组合和一些集中的“结构性空头”投注。正如我们在第三章中看到的走进狂野的空头市场,拥挤的空头头寸是不流动的,因此更容易出现波动率飙升。卖方不少,但勇敢的买方稀少。

空头方面的波动性推动整个投资组合。绩效不佳除以高剩余波动性只会产生不吸引人的波动率调整回报。

几乎没有历史性的下行保护

绝对方法在牛市中可能会发布正回报。但每当市场下跌时,绩效就会出现“软裁”。

大萧条(GFC)期间,人们本应该期望净头寸下降到零以下。毕竟,每个人都在谈论金融末日。如果多空参与者真的像他们声称的那样喜欢做空,净头寸应该下降到 0 以下。然而数字讲述了不同的故事。随着净贝塔达到+0.5,市场参与者仍然持有乐观态度。

采用绝对方法的从业者减少净头寸的方式是减少他们的多头头寸,并囤积现金。当到了在空头方面动手时,他们却胆怯了。多年来在牛市中交易使他们的空头卖出能力萎缩。如果你想打败迈克·泰森,你需要去健身房几次并且摆出你的笑脸。

较差的投资工具

绝对方法已经赢得了自身的存在危机。多空 1.0 既不是一个复杂的,也不是一个安全的投资工具。在任何一个方面,它都是一个较差的工具。它在牛市中的赚钱比共同基金和指数基金少。它在熊市中只比指数亏损少一点。经过费用后,投资者使用绝对方法比使用低技术水*的普通指数基金少积累的钱。与经典的共同基金相比,透明度和流动性都较低。因此,毫不奇怪,这些基金未能吸引和保留寻求稳定、不相关回报的养老金资金。绝对多空基金是为自己赚钱的企业,偶尔也为他们的投资者赚钱。

落后的指标

"La gravité est le bouclier des sots [引力是愚人的盾牌]。"

– 蒙特斯基耶,法国哲学家

股票不是洲际弹道导弹。它们不会只是因为它们无法获得足够的船用柴油来填满整个燃料箱而从天而降:

  1. 首先,他们落后于其直接竞争对手。

  2. 第二,他们落后于所在行业的其他股票。

  3. 第三,他们在所在行业中落后。

  4. 第四,他们表现不及更广泛的指数。

  5. 第五,他们最终在绝对值上下降。

关键问题在于,当这些股票出现在人们的雷达屏幕上时,它们已经失去了很多价值。在一个以创造性的多彩侮辱作为职业业余爱好的行业中,几乎没有什么比被称为滞后指标更刺耳的了。然而,在空头/多头业务中似乎是主导业务模式。

空头/多头市场参与者绝对不是低能儿。他们是受过高等教育、敬业、勤奋的人。以“看多强势”和“看空弱势”为正确的理念—绝对数据系列只是错误的数据集。作为替代方案,下一节将讨论使用相对系列而不是绝对价格的好处。

空头/多头 2.0:相对弱势方法

"真理本质上是不言自明的。一旦你清除了围绕它的无知之网,它就会清晰地闪耀出来。"

– 马哈特玛·甘地

指数如标准普尔 500、纳斯达克 100、富时 100 和 Topix 是其成分股的市值加权*均值。大约一半的股票在任何时间段内都会比指数表现得更好,而其余的则会更差。相对表现不佳的股票中有更多可供选择,而绝对价值下跌的股票则寥寥无几。

下面是计算相对系列的源代码:

def relative(df,_o,_h,_l,_c, bm_df, bm_col, ccy_df, ccy_col, dgt, start, end,rebase=True):
    '''
    df: df
    bm_df, bm_col: df benchmark dataframe & column name
    ccy_df,ccy_col: currency dataframe & column name
    dgt: rounding decimal
    start/end: string or offset
    rebase: boolean rebase to beginning or continuous series
    '''
    # Slice df dataframe from start to end period: either offset or datetime
    df = df[start:end] 

    # inner join of benchmark & currency: only common values are preserved
    df = df.join(bm_df[[bm_col]],how='inner') 
    df = df.join(ccy_df[[ccy_col]],how='inner')

    # rename benchmark name as bm and currency as ccy
    df.rename(columns={bm_col:'bm', ccy_col:'ccy'},inplace=True)

    # Adjustment factor: calculate the scalar product of benchmark and currency
    df['bmfx'] = round(df['bm'].mul(df['ccy']),dgt).fillna(method='ffill')
    if rebase == True:
        df['bmfx'] = df['bmfx'].div(df['bmfx'][0])

    # Divide absolute price by fxcy adjustment factor and rebase to first value
    df['r' + str(_o)] = round(df[_o].div(df['bmfx']),dgt)
    df['r' + str(_h)] = round(df[_h].div(df['bmfx']),dgt)
    df['r'+ str(_l)] = round(df[_l].div(df['bmfx']),dgt)
    df['r'+ str(_c)] = round(df[_c].div(df['bmfx']),dgt)
    df = df.drop(['bm','ccy','bmfx'],axis=1)

    return (df) 

接下来,我们将尝试这个功能。Softbank(9984.T)是一家在东京证券交易所TSE)上市的公司。它以日元交易。该公司在美国科技行业已经有*三十年的历史了。因此,Softbank 将与纳斯达克的美元进行对比:

ticker = '9984.T' # Softbank
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
start= '2018-12-30'
end = None
df =  round(yf.download(tickers= ticker,start= start, end = end, 
                        interval = "1d",group_by = 'column',                        auto_adjust= True, prepost= True,                         treads = True, proxy = None),2)
bm_df = pd.DataFrame()
bm_ticker = '^IXIC' #Nasdaq 
bm_col = 'nasdaq'
ccy_df = pd.DataFrame()
ccy_ticker = 'USDJPY=X'
ccy_col = 'JPY'
dgt = 5

bm_df[bm_col] =  yf.download(tickers= bm_ticker,start= start, end = end,
                             interval = "1d",group_by = 'column',                             auto_adjust = True, prepost = True,                              treads = True, proxy = None)['Close']
ccy_df[ccy_col] =  yf.download(tickers= ccy_ticker,start= start,                                end = end, interval= "1d",                               group_by = 'column',auto_adjust = True, 
                               prepost = True, treads = True,                                proxy = None)['Close']

df = relative(df,_o,_h,_l,_c, bm_df, bm_col, ccy_df, ccy_col, dgt, start, end,rebase=True)

df[['Close','rClose']].plot(figsize=(20,8),grid=True,
            title= 'Softbank Absolute in JPY vs relative to Nasdaq in USD rebased' ) 

此代码计算相对于数据框架开头的重新基准化的相对系列,与绝对系列进行比较,以 Softbank 为例。首先,我们下载 Softbank 的 OHLC 本地货币。然后我们下载基准纳斯达克和美元的收盘价。

我们通过保持布尔标志rebase=True来运行相对系列函数重新基准化到数据框架的开头。

图 4.2:Softbank 在绝对 JPY 与相对于美元纳斯达克的重新基准化

当电话失去了线缆时,人们随身携带它们,并逐渐束缚了自己。 自从电话束缚了人类以来,Softbank 一直是东京证券交易所的强大力量。 然而,与纳斯达克指数相比,以美元计价的软银表现**。 在本书的其余部分,我们将使用绝对价值的软银系列和仅用于示范目的的日元。 这个概念很简单:买入表现良好的,卖空表现不佳的,从价差中赚取利润。 关注超过指数的超额回报的想法并不新鲜。 共同基金经理根据其超额回报来评估。 当仅关注长期时,任务是增加表现优异者的权重并减少表现不佳者的权重。 与基准的权重差称为“主动资金”。

相对弱势方法采取了类似的方法。 长/短组合是两个相对账簿的净和。 长方向是经典的共同基金类型长账簿。 短方向由相对于指数的逆向表现的表现不佳者组成。 与共同基金的唯一区别在于,经理们在短期内采取主动对冲的策略,而不是远离表现不佳的人。 绩效来自长期的超额表现和短期的不足表现之间的差异。 下面是一个简单的例子。 通用电气、通用汽车和高盛在三个不同的行业中。 然而,它们有两个共同点。 首先,它们是同一个标准普尔 500 指数的组成部分。 其次,当它们组合在一起时,它们的股票代码具有这个可爱的缩写:GEMS。

下面的代码显示了绝对价值的价格系列,然后返回相对于基准的系列。

tickers_list = ['GE','GM','GS']

# Dataframes instantiation
gems = pd.DataFrame() 
start = '2020-03-31'
benchmark = yf.download(tickers= '^GSPC',start= start, end = None, 
                        interval = "1d",group_by = 'column',                        auto_adjust = True, prepost = True,                         treads = True, proxy = None)['Close']
failed = [] 
rel_ticker_list = []
for n,ticker in enumerate(tickers_list):
    try: #7 Download & process data
        gems[ticker] = yf.download(tickers= ticker,start= start,                                    end = None, interval = "1d",                                   group_by = 'column',                                   auto_adjust = True, prepost = True,                                    treads = True, proxy = None)['Close']
        gems['rel_'+ticker] = gems[ticker].div(benchmark * gems[ticker][0]) * benchmark[0]
        rel_ticker_list.append('rel_'+ticker)
    except:
        failed.append(ticker)
gems = gems[tickers_list+rel_ticker_list]
gems.plot(figsize= (20,8),secondary_y= rel_ticker_list,style=['r','b','g','r:','b:','g:'], 
          title= 'GEMS Absolute Prices vs Relative Series' ) 

该代码采取以下步骤:

  1. 实例化了gems数据框。 start可以是日期——例如2019-12-31,也可以是偏移期间,如–254。列表已实例化。

  2. 运行一个循环从 Yahoo Finance 下载价格信息。 将绝对系列添加到gems数据框中。

  3. 对于相对系列,需要除以基准并在系列开始时重新定位基准。

  4. rel_list_ticker附加到以el为前缀的 ticker 列表中。 这将用于以后排序列。

  5. 重新排序列并打印。

结果显示了通用电气GE)、通用汽车GM)和高盛GS)的绝对价格以及相对系列在虚线上:

图

图 4.3:通用电气(GE)、通用汽车(GM)和高盛(GS)的绝对价格与相对价格对比

图表说明相对系列对股票相对强势与市场的比较更具指示性。价格与基准相比在周期开始时重新调整,但它们提供了跨行业的均匀系列。起初,对一个上涨的股票进行空头操作似乎有些不自然。对于绝对回报型玩家来说,赔钱并不是一件自然的事情。为了理解这个概念,让我们通过设想在熊市中发生的情况来重新构思一下。当大熊猫袭击市场时,没有任何东西会上涨。这意味着你将寻找买入那些能够保持立场或者跌幅低于整体指数的防御型股票。在多头方面,你会比市场亏损少。通常情况下,你会购买非周期性的公用事业、铁路或食品股票。

相反,你会寻找那些下跌速度比基准更快的股票进行做空。这些往往是周期性股票,其表现随着经济周期的波动而波动,比如航空公司。顺便说一下,你可以将之前牛市的宠儿保留在你的投资组合中,但记得换边。牛市领头股往往会吸引末期动量玩家。这些是市场中最弱的参与者,晚来一步,没有真正的游戏计划。一旦形势严峻,他们就会退出,这导致突然的业绩退潮。与经典的绝对方法相比,相对系列开启了一整个新世界的可能性。以下是断言相对弱势方法优越性的 10 个理由。

在双方都能持续提供新思路的情况下,稳定的供应

指数通常是所有成分股的市值加权*均值。这意味着大约一半的股票将会跑赢市场,而另一半将落后于市场。起初,这种大量的想法对那些一直专注于绝对表现的市场参与者似乎令人不安。市场参与者可能会被诱惑继续使用绝对方法交易多头,而使用相对方法交易空头。这种糟糕的想法经常导致购买和做空表现不佳的股票。多头方面必须是与空头方面采用的策略和系列类型相反的镜像。

让我们重新审视我们在“无法降低与基准的相关性”部分编写的脚本,关于牛市和熊市中的股票数量。正如我们在那里提到的,该代码生成两个图表。我们最初使用了绝对系列进行横向计数,这也在这里显示出来:

图 4.4:使用绝对系列的标普 500 中处于牛市或熊市领域的股票

图表说明标普 500 指数已经处于牛市领域超过 12 年,中间偶有波动。总体来说,牛市股票远多于熊市股票。适合做空的候选股票寥寥无几。正如一句谚语所说,潮水能托起所有的船。

然而,让我们将这与相对系列进行比较。这是对每日条形图的简单横向计数。相比之下,下图显示了使用绝对和相对系列的牛市和熊市领域中的股票数量,价格除以指数的收盘价:

图 4.5:使用绝对系列与相对于指数的 S&P 500 中牛市或熊市领域中的股票数量

虚线代表相对于指数而言处于牛市或熊市领域的股票数量。毫不奇怪,牛市阵营大约有一半的股票,另一半处于熊市模式。这为双方提供了大量的选择。

成分清单不包括历史的纳入/删除。表现不佳、破产或被吸收的股票将从指数中删除。这造成了一种人为的向上漂移,称为幸存者偏见。幸存者偏见不会影响空头策略,因为它们的有效性仅针对最强的股票进行衡量。

无论指数如何,都有持续不断的新思路。绝对系列的波动非常大,取决于市场不断变化的情绪。同时,使用相对系列的牛市或熊市领域中的股票数量保持相对稳定。这意味着在任何给定时刻,书中的双方都有充足的想法。

随着广度变窄,表现不佳者的数量甚至可能超过表现优异者的数量。这直接违反了普遍存在的观念,即短期想法很少见。事实上,拥有更多表现不佳者而不是表现优异者并不罕见。

指数是其成分的市值加权*均值。它由最大的 100 个资本主导。在横向或动荡时期,较小的市值往往会被提醒牛顿物理学。对于流动性不足的股票,重力产生了沉重的影响。

专注于部门轮换

在绝对方法中,目标是控制市场的顶部和底部。每一个经验丰富的市场参与者都会告诉你,只有两种类型的人能够一直准确地掌握市场的顶部和底部。他们要么是健忘症患者,要么是江湖骗子,更多时候是两者兼而有之。当将所有事物重述为相对系列时,目标是专注于部门轮换。正如我们在上面的图表中看到的,不管是哪一方的股票数量随着时间的推移都没有太大的波动。这并不意味着相同的股票会永远表现不佳。市场可能会上涨数年,但它会随着时间的推移奖励不同的行业、部门,甚至是市值。使用相对弱势方法,这意味着购买新兴的表现优异者,并在早期卖空表现不佳者。想象一下当你告诉客户,在成功的熊市运动之后,现在是时候转向,押注早期周期股和小市值股,而周围充斥着末日的阴霾。

提供低相关性产品

将一切都除以基准,剥离了基础指数的影响。这样机械地去除了对指数的相关性。现在焦点是超过基准的超额回报。这可能会显得重复,但它却让人铭记于心。绝对系列在市场状况不同的情况下,名字的数量在不同的制度中波动很大。

相反,相对系列两边的名字数量相当一致。市场的波动并不会极大地影响候选池的规模,正如“两边都提供新想法的持续供应”部分所示。这也是基本的算术。将绝对系列除以指数,剥离了整个群体对基准的影响。剩下的只有货币影响和股票特定的表现。

提供低波动性产品

这是大量表现不佳者的直接结果。当有大量的空头候选者可供选择时,市场参与者在其投资组合中享有更大的多样化。他们也有更低的集中度。这降低了波动性。

降低借贷费用的成本

拥挤的空头借贷费用极其昂贵。机构股东很少遵守老海事荣誉准则。他们不会随船沉没。当表现持续不佳时,他们倾向于清算其头寸。这使得随着时间的推移,借贷变得更加困难。

另一方面,表现不佳的股票仍然受益于一些惯性。借贷接*一般抵押品,换句话说,便宜且充足。当坏消息传开,绝对空头玩家四处游荡时,相对空头可以将接力棒传递给他们不那么复杂的对手。前者可以转向廉价易借的空头,而后者则被迫咀嚼昂贵、干燥、难以借贷的名字。

提供可扩展性

绝对方法的一个问题是其缺乏可扩展性。在绝对价值下降的股票通常很受欢迎。拥挤的空头波动大且流动性差。很难建立大规模的盈利头寸。

在 2007 年,通常被称为量化基金的量化基金学习到,对拥挤的问题进行做空是有限度的。当两边都有充足的想法时,集中度可以保持较低,资产管理AUM)继续增长。

非对抗性

相对方法是非对抗性的。相对空头不需要将事情个人化。防御性公司的管理层明白,在牛市中他们的股票注定会表现不佳。他们不会因为他们的股票被空头卖出或者在这个前提下被多头买入而感到愤怒。相反,高飞的科技企业家知道,熊市并不是 IPO 的季节。

货币调整成为一种优势

具有区域或全球授权的经理需要处理多种货币和指数。将一切转换为相对于全球或区域基准的基金货币放在同一个竞技场上。

不需要额外的宏观视角、货币对冲、风险管理。一切都重新基于相同的货币和基准调整单位。例如,随着日元贬值 40%,日本市场猛涨。以日元(JPY)操作的经理在本地货币表现良好;而以美元计价的同行尽管持有完全相同的股票组合,但表现不佳。日元贬值吞噬了所有收益。

但管理一个货币调整后的相对组合并不直观。从股票选择到投资组合管理,一切都必须根据基准和基金货币进行调整。诸如进入、退出和头寸大小等决策都需要以货币调整后的相对价格进行。大多数数据供应商提供的绝对和本地货币的图表回答了相对市场参与者根本不应该问自己的问题。将股票的绝对价值与货币进行比较就像是在比较苹果和橙子。将整个投资范围转换为相对系列在一开始可能稍微复杂些,但在此后操纵起来却容易得多。

其他市场参与者无法猜测你的水*

市场参与者经常抱怨“他们”正在触发他们的止损,或者“他们”在操作他们的订单。市场参与者倾向于将止损设置在支撑/阻力水*、圆整数上。有些算法专门设计用于操纵挂单。当所有价格水*都相对于指数进行计算并进行货币调整时,那些狙击手算法就失效了。相对参与者反应的系列与绝对水*不同。

反过来,止损必须得到积极管理。在执行交易员的术语中,不能与来自交易所的价格匹配的订单无法成交。

你将会看起来像一个投资天才

正如我们之前所见,股票并不会毫无征兆地绝对价值下降。表现不佳始于它们的竞争对手,然后延伸至行业、部门和更广泛的市场,最后以绝对价值暴跌。在相对基础上做空可能在一段时间内略微痛苦。然而,对于那些专注于绝对价格的人来说,这似乎是有远见的。

一图胜千言。以下图表绘制了威尔斯法尔戈WFC)的相对和绝对表现。

ticker = 'WFC'
benchmark = '^GSPC'
tickers_list = [benchmark] + [ticker]

data = round(yf.download(tickers= tickers_list,start= '2015-09-07', end = None,
            interval = "1d",group_by = 'column',auto_adjust = True, 
            prepost = True, treads = True, proxy = None)['Close'],2)

data['r'+str(ticker)] = round(data[ticker].div(data[benchmark])*data[benchmark][0] ,2)
data[[ticker,'r'+str(ticker)]].plot(figsize=(20,8),grid=True,
title= str.upper(ticker)+ ' Absolute vs Relative series') 

这产生了以下图表:

图示

图 4.6:威尔斯法尔戈在绝对和相对系列中丑闻爆发前一年(至今)

该图表从丑闻爆发前一年零一天开始。在绝对股价反映出即将发生的事情之前,表现不佳早已开始。相对表现提前数月折扣了绝对表现。

现在,想象一下,即使在丑闻爆发前 6 个月,你也已经开始做空富国银行了。对于那些急于寻找一个好的做空者的所有投资者来说,还有比这更好的卖点吗?没有比绝对值图表更好的营销说辞,它绘制了你根据与指数相对变化所进行的交易。想象一下,早在它们成为新闻之前,你就在所有世界上的恩隆、雷曼、通用汽车和柯达的短头位置上锚定了。

在所有人之前进入市场会给你一个安全边际。头寸不太容易受到熊市反弹的影响。然而,这只是问题的一半。在做空方面退出可能会很混乱。随着做空交易的普及,成交量逐渐减少。这就是相对方法提供决定性优势的地方。在某个时候,卖压将会结束。相对做空者有足够的时间来*仓,而他们的绝对对手则会加倍进行毒辣的攻击。股票开始表现优于市场,一开始几乎察觉不到,然后顽固地上升,最终挑衅地上升。这总会使那些依靠市场双底的绝对基本做空者措手不及。

摘要

在本章中,我们概述了从绝对 OHLC 价格转向相对系列的好处。绝对参与者是滞后指标,而相对参与者则领先一步。采用本章概述的方法的市场参与者将拥有明显的优势。他们将能够在众人之前建立和清算头寸。他们将看起来像是有先见之明的投资天才。他们将有更多的选择。他们的投资组合与市场的相关性更低,波动性也更低。这些都是投资者在寻找的特征。

一旦所有股票相对于基准在基金货币中重新计算,下一步就是根据它们的市场情况重新分类投资范围:看涨、看跌、横盘。我们将在下一章中详细介绍这一点。

第五章:制度定义

在拿破仑战争期间,资源有限的野战外科医生不得不迅速决定谁需要手术,谁可以在没有手术的情况下生存,以及那些不幸的人,无法做任何事情。分类是在有限的时间和资源中尽可能有效和人道的分配的必然产物。在股票市场上,制度是分类的另一个词。有些是看涨的,有些是看跌的,有些是不确定的。

市场往往会持续“错误”的时间比投资者坚持你的时间要长。在进行深入分析之前,将股票分为不同的制度桶——进行分类——是资源的有效分配。这种初步分类的目标不是预测股票可能会、会或者应该走向何方,而是实践已经失传的主动倾听市场的艺术。

一些市场参与者喜欢花时间和资源建立那些顽固地违背理性的股票的看跌论点。这并不是高效的,有两个原因。首先,他们期望回归均值。在多头方面,他们交易趋势并持有表现优异者,期待它们继续表现良好。与此同时,在空头方面,他们进行均值回归并期待昂贵的股票吞下“谦卑的馅饼”,再次回到廉价。

正如我们将在接下来的章节中分析的那样,趋势跟随和均值回归具有相反的回报和风险特征。长期趋势跟随和短期均值回归并不能降低风险,而是加剧了风险。暂时来说,市场参与者必须做出选择。他们要么交易预期趋势会发展的趋势,要么交易预期不规范的地方会纠正的不规范。当他们选择同时交易趋势和不规范时,他们的投资风格是不一致的。他们邀请了每种风格的最坏结果,而这种情况不出所料地往往会在最糟糕的时刻同时发生。

其次,期望股票回归本质上就像试图时机抄顶。这就像站在铁轨中间期待一列又一列货运火车停下来一样。牛市制度往往会比投资者对勇敢的耐心更长久。在放空之前,等待更多信息浮出水面并且市场趋势转为熊市是更为谨慎的做法。

作为一个不同的方法,确定市场制度是一件真正有助于基本面卖空者的事情。他们经常会过早出现。他们在更广泛市场开始考虑信息之前就下注了。卖空大师和可怕的失败之间的差距是 6 个月。在 1999 年卖空互联网股票,然后在 2000 年你就会在大学里教无聊的数学了。在 2000 年一月底就卖空同样的股票,那么一个新的卖空之星就诞生了。

在接下来的几节中,我们将查看各种制度定义方法,然后进行比较:

  • 导入库

  • 创建图表函数

  • 突破/崩溃

  • 移动*均线

  • 高高低低

  • 地板/天花板

  • 方法比较

  • 让市场制度决定最佳策略

您可以通过以下链接访问本章中所有图片的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。您还可以通过本书的 GitHub 存储库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

对于本章和本书的其余部分,我们将使用pandasnumpyyfinancematplotlib库。我们还将使用来自 ScientificPython 库的find_peaks

所以,请记得首先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt
from scipy.signal import find_peaks 

创建绘图函数

在我们视觉上比较各种制度方法之前,让我们发布名为graph_regime_combo的彩色图表函数的源代码。随着我们逐步揭示每种方法,参数将逐渐有意义。

代码如同日本麻酱米饭一般易于消化,这是日本婴幼儿、老年人和外国人,如作者,在日本因窒息而死亡的常见原因。但结构很简单,就像作者一样。一切都取决于是否在rg变量中实例化了地板/天花板方法。如果存在地板/天花板,则它将替代其他一切。如果没有,则会打印其他两种方法(突破和移动*均线交叉)。ax1.fill_between方法标识边界。阅读所有内容以了解条件。其余部分*淡无奇:

#### Graph Regimes ####
def graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,                       ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi):

    '''
    https://www.color-hex.com/color-names.html
    ticker,df,_c: _c is closing price
    rg: regime -1/0/1 using floor/ceiling method
    lo,hi: small, noisy highs/lows
    slo,shi: swing lows/highs
    clg,flr: ceiling/floor
    rg_ch: regime change base
    ma_st,ma_mt,ma_lt: moving averages ST/MT/LT
    lt_lo,lt_hi: range breakout High/Low LT 
    st_lo,st_hi: range breakout High/Low ST 
    '''
    fig = plt.figure(figsize=(20,8))
    ax1 = plt.subplot2grid((1,1), (0,0))
    date = df.index
    close = df[_c]
    ax1.plot_date(df.index, close,'-', color='k',  label=ticker.upper()) 
    try:
        if pd.notnull(rg):  
            base = df[rg_ch]
            regime = df[rg]

#### removed for brevity: check GitHub repo for full code ####

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True)
    ax1.xaxis.label.set_color('k')
    ax1.yaxis.label.set_color('k')
    plt.xlabel('Date')
    plt.ylabel(str.upper(ticker) + ' Price')
    plt.title(str.upper(ticker))
    plt.legend()
#### Graph Regimes Combo #### 

现在这段致命的代码已经解决了,幸存者可以继续进行下一阶段:范围突破。

突破/突破

“风筝最高飞,逆风飞翔。”

—温斯顿·丘吉尔

这是最古老和最简单的趋势跟踪方法。它适用于牛市和熊市。如果价格在x个周期内创下新高,则为牛市。如果价格在x个周期内创下新低,则为熊市。这种方法在计算上很容易实现。

流行的持续时间是 252 个交易日(相当于 52 周)、100 个交易日和 50 个交易日。下面是这种制度方法的简单表达:

def regime_breakout(df,_h,_l,window):
    hl =  np.where(df[_h] == df[_h].rolling(window).max(),1,
                                np.where(df[_l] == df[_l].                                    rolling(window).min(), -1,np.nan))
    roll_hl = pd.Series(index= df.index, data= hl).fillna(method= 'ffill')
    return roll_hl

ticker = '9984.T' # Softbank ticker
start= '2016-12-31'
end = None
df = yf.download(tickers= ticker,start= start, end = end,                 interval = "1d",group_by = 'column',                 auto_adjust = True, prepost = True, 
                 treads = True, proxy = None)

window = 252
df['hi_'+str(window)] = df['High'].rolling(window).max()
df['lo_'+str(window)] = df['Low'].rolling(window).min()
df['bo_'+ str(window)]= regime_breakout(df= df,_h= 'High',_l= 'Low',window= window)
df[['Close','hi_'+str(window),'lo_'+str(window),    'bo_'+ str(window)]].plot(secondary_y= ['bo_'+ str(window)], 
        figsize=(20,5), style=['k','g:','r:','b-.'],        title = str.upper(ticker)+' '+str(window)+' days high/low') 

这段代码的功能很简单:

  1. 如果高点是x周期的最高点,则hl1

  2. 否则,如果低点是x周期的最低点,则hl-1

  3. 如果这些条件都不成立,则hl为 N/A。

  4. 我们想要使用fillna方法沿着缺失值传播最新值。首先,我们将numpy数组转换为pandas系列。

  5. 然后,我们使用fillna向前填充方法填充缺失值。

  6. 下载数据,运行函数,并绘制图表:

    图 5.1:软银一年最高/最低制度突破定义

当价格在整理或横盘市场之后突破时,这种范围突破策略效果非凡。横盘市场是上行或下行趋势之间的暂时期间,旧制度已死,新制度尚不明显。在横向波动的市场中,价格在一定范围内波动。

公牛与熊在一场吉尔伽美什史诗般的战斗中激烈争斗。当价格突破上界或下界时,这表明一方已经放弃了。被压抑的能量得以释放。价格毫不费力地沿着最小阻力线移动。因此,这种突破方法是范围突破/突破的首选武器。

这种方法的主要缺点是其内置的滞后性,这是由持续时间引起的。在财务修订主义的行话中,等待期被称为确认。市场参与者很少有耐心等待 50 天、100 天,甚至一年才最终找到一些解决方案。时间就是金钱。拖欠租金的股票应该被减少或者被赶走。使用这种长期持续时间的市场参与者可能希望将时间退出重新引入到他们的策略中。

这种方法的主要优点是计算简单和稳定性。主要缺点是其固有的滞后性和回撤大量利润的不适。这将我们引向下一个迭代:不对称的范围突破策略。

对突破制度定义方法的进一步完善包括为进入和退出分离的周期。例如,传奇的芝加哥海龟交易者在 50 日最高点进入,20 日最低点退出:

# CHAPTER 5 Turtle for dummies

def turtle_trader(df, _h, _l, slow, fast):
    '''
    "    _slow: Long/Short direction\n",
    "    _fast: trailing stop loss\n",
    '''
    _slow = regime_breakout(df,_h,_l,window = slow)
    _fast = regime_breakout(df,_h,_l,window = fast)
    turtle = pd. Series(index= df.index, 
                        data = np.where(_slow == 1,np.where(_fast == 1,1,0), 
                                np.where(_slow == -1, np.where(_fast ==-1,-1,0),0)))
    return turtle
slow = 50
fast = 20
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
df['bo_'+ str(slow)] = regime_breakout(df,_h,_l,window = slow)
df['bo_'+ str(fast)] = regime_breakout(df,_h,_l,window = fast)
df['turtle_'+ str(slow)+str(fast)] = turtle_trader(df, _h, _l, slow, fast)
rg_cols = ['bo_'+str(slow),'bo_'+ str(fast),'turtle_'+ str(slow)+str(fast)]
df[['Close','bo_'+str(slow),'bo_'+ str(fast),'turtle_'+ str(slow)+str(fast)] ].plot(
    secondary_y= rg_cols,figsize=(20,5), style=['k','orange','g:','b-.'],
                                 title = str.upper(ticker)+' '+str(rg_cols)) 

这种不对称的持续时间使交易者能够在灵活的市场中获得小利润:

图 5.2:软银的不对称制度突破持续时间(海龟入门者策略)

上述图表显示了软银的收盘价,慢速制度突破(橙色实线),快速制度突破(绿色虚线),以及两者的组合蓝色虚点线。蓝色虚点线提供入场和出场信号。这有点难以阅读,因此我们将在下面使用一个视觉上更友好的图表。

上面概述的海龟策略是受传奇海龟交易者启发的一种基本脚本。它由两个范围突破制度组成。较慢的持续时间用于进入。较快的持续时间用于退出。这种入场和出场的不对称持续时间依赖于一项古老的原则:谨慎和审慎地确认趋势,但快速和果断地削减损失并保护利润。这最后一个制度将从现在起改名为Turtle for dummies

我们将在本书中多次使用这种基本策略来说明例子,纯粹是为了教育目的。但是,请不要在家里这样做——这对于教育目的而言是足够现实的,但过于简单,无法用于实际的盈利。

使用graph_regime_combo更直观地表示海龟入门者策略如下:

ma_st = ma_mt = ma_lt = 0
rg=lo=hi=slo=shi=clg=flr=rg_ch = None
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
bo_lt = 200
bo_st = 50

lt_lo = df[_l].rolling(window= bo_lt).min()
lt_hi = df[_h].rolling(window= bo_lt).max()
st_lo = df[_l].rolling(window= bo_st).min()
st_hi = df[_h].rolling(window= bo_st).max()
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

这给出了下面的图表:

5.3:软银制度使用乌龟交易员方法。较暗的区域是较短时间范围

更长的持续时间给出了方向;长或短。这是蓝线,基于50-day的最高/最低点。更短的持续时间是止损。我们将在第七章提高您的交易优势中详细讨论止损。较短的持续时间通过缩小范围来保护利润。这样做的反面是交易频率增加。乌龟策略的这组参数在波动市场中效果不佳,正如我们在2018年整年都能看到的那样。在2019年的横向市场中,它也遇到了困难。

移动*均线交叉

移动*均线是另一种流行的制度定义方法。这种方法非常简单和普遍,以至于即使是声称从不看图表的最顽固的基本分析师,也喜欢使用200-day的简单移动*均线。这种方法也很容易计算。对于移动*均线的类型可能还有进一步的细化,从简单到指数、三角形、自适应都有。然而,原则是相同的。当快速移动*均线高于较慢的时候,制度是看涨的。当它低于较慢的时候,制度是看跌的。下面的代码展示了如何使用简单移动*均线和指数移动*均线(分别是SMAEMA)计算制度:

#### Regime SMA EMA ####
def regime_sma(df,_c,st,lt):
    '''
    bull +1: sma_st >= sma_lt , bear -1: sma_st <= sma_lt
    '''
    sma_lt = df[_c].rolling(lt).mean()
    sma_st = df[_c].rolling(st).mean()
    rg_sma = np.sign(sma_st - sma_lt)
    return rg_sma

def regime_ema(df,_c,st,lt):
    '''
    bull +1: ema_st >= ema_lt , bear -1: ema_st <= ema_lt
    '''
    ema_st = df[_c].ewm(span=st,min_periods = st).mean()
    ema_lt = df[_c].ewm(span=lt,min_periods = lt).mean()
    rg_ema = np.sign(ema_st - ema_lt)
    return rg_ema

st = 50
lt = 200
df['sma_' + str(st) + str(lt)] = regime_sma(df, _c='Close', st= st, lt= lt)
df['ema_' + str(st) + str(lt)] = regime_ema(df, _c='Close', st= st, lt= lt)

ohlc = ['Open','High','Low','Close'] 
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
rgme_cols = ['sma_' + str(st) + str(lt), 'ema_' + str(st) + str(lt),'turtle_'+ str(slow)+str(fast) ]
df[['Close','sma_' + str(st) + str(lt), 'ema_' + str(st) + str(lt),'turtle_'+ str(slow)+str(fast)] ].plot(
    secondary_y= rgme_cols,figsize=(20,8), style=['k','orange','m--','b-.'],
                                 title = str.upper(ticker)+' '+str(rgme_cols)) 

这产生了下面的图表:

5.4:软银制度使用乌龟突破,简单移动*均线和指数移动*均线

在这里,我们比较了三种制度方法。我们有我们新鲜出炉的,最好的朋友Turtle for dummies在虚线蓝线上。我们有橙色的简单移动*均线,和紫色虚线的指数移动*均线。移动*均线系列的结果是可预见的接*。指数移动*均线比简单移动*均线更具反应性。现在我们可以使用graph_regime_combo图表函数来可视化结果。

rg=lo=hi=slo=shi=clg=flr=rg_ch = None
lt_lo = lt_hi = st_lo = st_hi = 0

ma_st = df[_c].rolling(window=50).mean()
ma_mt = df[_c].rolling(window=200).mean()
ma_lt = df[_c].rolling(window=200).mean()
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]

graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

该函数可容纳最多三个移动*均线。要获得仅具有两个移动*均线的图表,就像在这里所做的那样,请将中期和长期设置为相同的值(在这种情况下,中期和长期都设置为200)。下面是移动*均线交叉制度的可视化呈现。浅绿色和浅红色区域是制度看涨或看跌且盈利的地方。深绿色和深红色区域是制度看涨或看跌但无盈利的地方:

5.5:软银的交叉区域较暗的区域是亏损区域

这种策略在横向和波动市场中表现不佳。快速和慢速移动*均线收敛为低幅度正弦振荡的*坦线。交易频率和亏损率增加,而胜率下降。

实例化三个移动*均线的更简洁方法是通过列表推导。首先,我们创建一个移动*均变量列表。其次,我们通过列表推导实例化变量。让我们用几个列表推导来写上面的内容:

mav = [50, 200, 200]
ma_st,ma_mt,ma_lt = [df[_c].rolling(mav[t]).mean() for t in range(len(mav))]

bo = [50, 252]
st_lo,lt_lo = [df[_l].rolling(bo[t]).min() for t in range(len(bo))]
st_hi,lt_hi = [df[_h].rolling(bo[t]).max() for t in range(len(bo))]
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]

graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

这将是这样的:

图 5.6:Softbank 交叉适用于菜鸟的海龟

这张越来越色彩缤纷的图表显示了两种制度方法的组合。不幸的是,它增加了更多的混乱而不是解决问题。市场参与者有时会试图添加多个条件,希望筛除假阳性。但不幸的是,接受随机性要比试图根除随机性更容易。

两线交叉是移动*均线交叉方法中最受欢迎的版本。较慢的线定义制度,而较短的持续时间线计时进出。最受欢迎的持续时间是 50/200,被称为黄金/死亡交叉。理论上,这种组合是有意义的。200 天是一个强大的长期衡量指标,而 50 天是一个良好的动量指标。在实践中,这种组合的命中率很差。它只适用于大的长期趋势。不幸的是,它们很少出现,因此胜率大约为 20%。其余的时间,更快的移动*均线像职业政客一样在较慢的移动*均线周围来回摇摆。

这些弱点导致移动*均线的狂热者将其发展到下一个阶段的三个移动*均线。在以下示例中,我们通过添加另一个持续时间较短的移动*均线来改进之前的 50/200 金叉移动*均线交叉。为了简单起见,我们使用 20、50 和 200 天。200 天给出了制度,而 20/50 排列给出了进出。

我们所要做的就是在以下代码中更改一个变量:

rg=lo=hi=slo=shi=clg=flr=rg_ch = None
lt_lo = lt_hi = st_lo = st_hi = 0

mav = [20, 50, 200]
ma_st,ma_mt,ma_lt = [df[_c].rolling(mav[t]).mean() for t in range(len(mav))]
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]

graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

我们可以在下面看到产生的图表:

图 5.7:Softbank 三重移动*均线交叉

最长的持续时间决定制度。中期和短期持续时间分别计时进入和退出。与其长段落不如用以下逻辑最好地概括:

  1. 长期:当短期移动*均线最高时进入并保持长期持有,其次是中期和长期移动*均线

  2. 短期:当短期移动*均线低于中期移动*均线时进入并保持空头,中期移动*均线需要低于长期移动*均线。

  3. 否则:中性,无持仓。

这种方法可能是在遵循长期已建立的趋势和保持良好风险管理之间取得的最实际的折中。

与我们之前看到的双移动*均图不同,三移动*均线不会长时间保持错误方向。它在早期削减头寸方面做得更好。这些是无色和较短的较暗区域。另一方面,该方法的缺点是交易频率的增加。另一个缺点是该方法的固有滞后性。正如图表的中间部分所示,在横向市场中,价格会在产生信号之前朝任一方向移动相当多。

市场参与者放弃移动*均线方法的主要原因是横向市场。当市场横向波动时,移动*均线会相互振荡。这会产生许多错误的信号,这些信号倾向于侵蚀金融和情绪资本基础。在经历了几次代价高昂的错误开始后,市场参与者往往会寻找更少噪音的方法。

与调整移动*均持续时间或完全放弃该方法不同,更好的解决方案可能是调整赌注大小。在出现横向市场的第一个迹象时减小规模,然后随着趋势的增长增加权重。

更高的高点/更高的低点

这是另一种流行的方法。趋势上升的股票会创造更高的高点和更高的低点。相反,趋势下降的股票会按顺序创造更低的低点和更低的高点,因此表明持续的弱势。这种方法在直觉上是有道理的。不幸的是,统计上并不像看起来那么稳健。市场有时会打印出低/高低/高,从而使计算失效,然后恢复其行程。其次,此方法需要同时满足三个条件:

  1. 一个更低的低点。

  2. 一个更低的高点。

  3. 两个更低的低点和更低的高点条件必须按顺序满足,这只适用于有序的市场。

这三个条件必须按照精确顺序连续满足,才能使制度转为熊市。市场是随机的,比人们一般认为的更嘈杂。

此方法的主要优点是进出场。在多方面,低点买入,高点退出。在空头方面,高点卖出,低点退出。这些反向趋势的进出口使市场参与者能够获利。此外,止损在多方面明确定义为更高的低点,在空方面明确定义为更低的高点。

总的来说,这种方法的前提是合乎逻辑的。创造更高的高点和更高的低点的股票被拉向上升,反之亦然。不幸的是,这种方法在嘈杂的市场中表现不佳,那里没有清晰的高点和低点的连续性,因此我在本章中省略了代码。

以下方法使用相同的摆动高点和摆动低点以更强大的方式定义制度。它简单且统计上稳健。

地板/天花板法

该方法最初是对更高高/更低低方法的变体。每个人都直观地使用过它,然而它显然是如此明显,以至于似乎没有人费心将其形式化。与更高高/更低低方法不同,制度只需满足以下两个条件之一即可更改:

  1. 熊市:摆动高点必须明显低于峰值。

  2. 牛市:摆动低点必须明显高于底部。

即使制度转变,摆动也不必连续。例如,市场有时会飙升,然后退却并打印出一段时间的横向波动。这些时期被称为整理。直到一个摆动高点明显低于峰值,制度才会转为熊市。

经典定义始终有效,无论时间框架和资产类别如何。在牛市中,低点将明显高于底部。相反,在熊市中,高点将明显低于峰值。

随机性触发了以简洁优雅的方式处理的异常。有两种方法:

  1. 保守的

    • 如果制度是熊市的,价格越过天花板,制度就会转为牛市。

    • 如果制度是牛市的,价格越过地板,制度就会转为熊市。

  2. 积极的

    • 如果制度是熊市的,价格越过发现摆动高点,制度就会变成牛市。

    • 如果制度是牛市的,价格越过发现摆动低点,制度就会转为熊市。

这种地板/天花板方法只有两种制度:牛市或熊市。横向制度是在更广泛的牛市或熊市背景中的暂停。该方法为制度定义带来了稳定性。在实践中,没有什么比围绕移动*均线来回翻转更令人沮丧的了。稳定性使市场参与者能够更好地管理其持仓。

地板/天花板方法在概念上很简单。但是计算起来并不容易。这是一个两步过程:

  1. 摆动检测

  2. 制度定义

市场不是直线上涨的。它沿着主导趋势上下波动。它沿途标记局部高点和低点。这些被称为摆动高点摆动低点

摆动检测占了地板/天花板方法的 80%。并非所有的摆动高低点都是*等的。主要困难在于将噪音与信号分离。由于制度定义是基于摆动的,错误的摆动检测不可避免地导致错误的制度定义。

代码逻辑很简单。它依赖于两个测试:重测和距离。我们将从摆动高点到摆动低点的整个序列进行,如图 5.8所示:

  1. 价格从先前的摆动低点上升到新的高点。

  2. 价格从那个历史新高下跌。

  3. 价格重测那个历史新高,但失败了,并低于那个历史新高后的低点。

  4. 一旦价格跌破最高低点,卖方可能掌握主导地位。该算法设计为在创历史新高后不断重置到最高低点。

以下是摆动低点的等效步骤:

  1. 价格打印出最低点:第一个低点。

  2. 它反弹到第一个高点。

  3. 价格回落到其最新低点,但未能达到最低点。

  4. 价格随后开始向上走动。它要么突破第一个高点(始终是最低点后的最高点)或者打印一个较低的高点,称为最新高点。当价格收盘高于第一个或最新的高点时,这表明买家现在可能掌控着局势。

    该序列重复出现,直到价格收盘高于或低于最新的高点或低点。单独看,重新测试并不具有统计学意义。它们发生得相当频繁。当与距离测试相结合时,重新测试往往更具意义。

  5. 距离测试:这是从摆动高点到最低点的距离。此测试可以以波动率单位或百分比点单位进行。距离越远,越有可能表明趋势耗尽:

    图 5.8:摆动检测的视觉解释:距离和重新测试

现在,让我们放大看看整体情况。上图中的摆动高点是下图中的峰值:

图 5.9:楼层/天花板制度定义

次轴上的线是制度。制度在找到比底部高得多的摆动低点后变为看涨。这个摆动低点现在是制度变更线。如果价格跌破该水*,制度将变为看跌。这发生在 2020 年第一季度,此时制度变为看跌。价格再次突破该水*,制度转为看涨。价格在 2021 年初创下历史新高,随后下跌,然后反弹,但在高点之前转跌。制度变为看跌。现在是时候从多头转为空头了。然而,该问题的借贷成本昂贵得令人望而却步,因此那笔丰厚的交易未能成行。

在接下来的几节中,我们将介绍计算此内容所需的源代码。这个概念框架受到了比利时数学家本尼迪克特·曼德布罗特关于分形的开创性工作的启发。我们从一系列嘈杂的小高点和低点开始,然后使用前一系列缩小的数据。这种方法比其他方法更加计算密集。然而,结果出奇地直观。它大致分为两个阶段:摆动检测制度定义。摆动检测是一系列小函数。

摆动检测

摆动检测分为两部分:历史摆动和最后摆动调整。前两个函数,historical_swingshilo_alternation,完成了 90% 的工作。其余部分是一系列小函数,确保最后的摆动是相关的。乍一看这可能看起来有点冗长,所以我们将逐步介绍所有函数并解释它们的相关性。

历史摆动和高/低交替

让我们从下载历史价格开始。我们使用 SPY,这是标普 500 的一个代理交易所交易基金ETF),但如果您愿意,您可以尝试使用不同的代码:

# CHAPTER 5 Swing detection
ticker = 'SPY' 

start= '2016-12-31'
end = None
raw_data = round(yf.download(tickers= ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None),2)
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))] 

接下来,我们将按顺序逐个呈现每个函数,并用图表或属性说明进展。我们从上一个函数结束的地方继续,并前进。最后,我们将一次性发布所有函数的完整总结,并发布一个图表:

#### hilo_alternation(hilo, dist= None, hurdle= None) ####
def hilo_alternation(hilo, dist= None, hurdle= None):
    i=0    
    while (np.sign(hilo .shift(1)) == np.sign(hilo)).any(): # runs until duplicates are eliminated
        # removes swing lows > swing highs
        hilo.loc[(np.sign(hilo.shift(1)) != np.sign(hilo)) & # hilo alternation test 
                 (hilo.shift(1)<0) &  # previous datapoint: high
                 (np.abs(hilo.shift(1)) < np.abs(hilo) )] = np.nan # high[-1] < low, eliminate low 

        hilo.loc[(np.sign(hilo.shift(1)) != np.sign(hilo)) &  # hilo alternation
                 (hilo.shift(1)>0) &  # previous swing: low
                 (np.abs(hilo ) < hilo.shift(1))] = np.nan # swing high < swing low[-1]

#### removed for brevity: check GitHub repo for full code ####
#### hilo_alternation(hilo, dist= None, hurdle= None) ####
#### historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None) #### 
def historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None):

    reduction = df[[_o,_h,_l,_c]].copy() 
    reduction['avg_px'] = round(reduction[[_h,_l,_c]].mean(axis=1),2)
    highs = reduction['avg_px'].values
    lows = - reduction['avg_px'].values
    reduction_target =  len(reduction) // 100

    n = 0
    while len(reduction) >= reduction_target: 
        highs_list = find_peaks(highs, distance = 1, width = 0)
        lows_list = find_peaks(lows, distance = 1, width = 0)
        hilo = reduction.iloc[lows_list[0]][_l].sub(reduction.iloc[highs_list[0]][_h],fill_value=0)

#### removed for brevity: check GitHub repo for full code ####
#### historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None) ####

df = raw_data.copy()
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
rhs = ['Hi1', 'Lo1','Hi2', 'Lo2', 'Hi3', 'Lo3']
rt_hi,rt_lo,_hi,_lo,shi,slo = [rhs[h] for h in range(len(rhs))]

df= historical_swings(df,_o,_h,_l,_c,dist= None, hurdle= None)

df[[_c,rt_hi,rt_lo,_hi,_lo,shi,slo ]].plot(
    style=['grey','y.', 'c.','r.', 'g.', 'rv', 'g^'],
    figsize=(20,5),grid=True, title = str.upper(ticker))
df[[_c,shi,slo]].plot(style=['grey','rv', 'g^'],
        figsize=(20,5),grid=True, title = str.upper(ticker)) 

hilo_alternation 函数循环遍历减少的数据帧,直到系列被整齐地构成交替的高点和低点。它消除:

  1. 相邻相同方向的高点和低点:高点被赋予负号。低点有一个正号。当有两个连续的高点或低点时,最低值标记着极端点。

  2. 高于周围高点的低点。随机性无法消除:理论上,这不应该存在,但在实践中,异常仍然存在。

  3. 嘈杂的短距离高点和低点。距离测试并不完全相关,因为交替循环包含在更大的多级循环中。这是算法的分形部分,我们在缩小图像的同时寻找相同的模式。然而,该特征是一个优雅的选项,可以缩短循环的次数。

  4. 在每次迭代结束时,使用 dropna 方法减少 hilo df

historical_swings 函数采取以下步骤:

  1. 减少数据帧:复制主数据帧,并从高、低和*均值实例化一个新系列。

  2. 循环以减少数据帧。

  3. 计算两组高点和低点(通过给*均系列分配负号)。高点的唯一要求是前后的条必须较低,反之亦然。

  4. 运行 hilo_alternation 函数以减少数据帧。

  5. 填充减少的数据帧,并通过 dropna 方法进一步减少。

  6. 为每个级别填充主数据帧。当减少的长度<1% 的主数据帧,或者不再可能减少,或者经过 10 次迭代时停止。

以上代码返回了这个非常嘈杂的图表:

图 5.10:SPY 分形高点/低点 1 到 3 级

第一级是标有 Hi1 和 Lo1 的小点,位于收盘价的上方和下方。第 2 级是标有 Hi2 和 Lo2 的红色和绿色点。它不太频繁,但仍然相对嘈杂。接下来,我们真的需要识别有意义的转折点来进行分析。所以,我们上升一个级别。三角形是第 3 级。价格已经经过了两次筛选。原始数据帧已经减少了 99%。

以下图表只显示价格和 3 级数据:

图 5.11:SPY 历史摆动

最后一个三角形在最高收盘价下方。这显然是一个误报。高点显然不是最高点,也没有后跟一个低点。其余的函数将调整最后一个摆动。所以,让我们让这个误报消失:

  1. 波动高点:价格持续高于最新的波动高点。

  2. 波动低点:价格持续低于最新的波动低点。

cleanup_latest_swing() 函数从最新的波动高点和低点中移除了错误的阳性:

#### cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo) ####
def cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo): 
    '''
    removes false positives
    '''
    # latest swing
    shi_dt = df.loc[pd.notnull(df[shi]), shi].index[-1]
    s_hi = df.loc[pd.notnull(df[shi]), shi][-1]
    slo_dt = df.loc[pd.notnull(df[slo]), slo].index[-1] 
    s_lo = df.loc[pd.notnull(df[slo]), slo][-1] 
    len_shi_dt = len(df[:shi_dt])
    len_slo_dt = len(df[:slo_dt])

    # Reset false positives to np.nan
    for i in range(2):

        if (len_shi_dt > len_slo_dt) & ((df.loc[shi_dt:,rt_hi].max()> s_hi) | (s_hi<s_lo)):
            df.loc[shi_dt, shi] = np.nan
            len_shi_dt = 0
        elif (len_slo_dt > len_shi_dt) & ((df.loc[slo_dt:,rt_lo].min()< s_lo)| (s_hi<s_lo)):
            df.loc[slo_dt, slo] = np.nan 
            len_slo_dt = 0
        else:
            pass

    return df
#### cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo) ####

df[[_c,shi,slo]].plot(style=['grey','rv', 'g^'],
        figsize=(20,5),grid=True, title = str.upper(ticker) + ' pre-adjustment')

df = cleanup_latest_swing(df, shi,slo,rt_hi,rt_lo)

df[[_c,shi,slo]].plot(style=['grey', 'rv', 'g^'],
        figsize=(20,5),grid=True, title = str.upper(ticker) + ' post-adjustment') 

代码执行以下步骤:

  1. 代码标识了最新的波动低点和高点。

  2. 识别最*的波动。

  3. 如果是错误的阳性,则指定为 N/A。

以下图表在调整前后说明了该函数从数据中移除了错误的阳性:

图 5.12:调整前的 SPY:最后的波动高点和低点是错误的阳性

图 5.13:调整后的 SPY:两个波动都被删除

这两个图表是不言自明的。最后两个三角形必须被移除。最后的波动低点由绿色三角形表示,高于前一个波动高点。此外,由于没有更低的波动低点,因此该波动高点无效。因此,当我们对最后两个波动进行一次循环时,两者都被移除。现在图表一直回溯到 2020 年 3 月的低点。接下来,我们将使用 latest_swing_variables() 函数实例化所有在后续过程中所需的变量。此函数计算将在接下来的几个函数中使用的变量。它们分别是:

  • ud: 方向,上升 +1,下降 -1

  • bs: 基础,要么是波动低点要么是高点。

  • bs_dt: 波动日期。

  • _rt: 将用于检测波动的系列名称。对于波动高点,为重新测试低位 rt_lo,对于波动低点,为重新测试高位 rt_hi

  • _swg: 用于赋值的系列;shi 表示波动高点,slo 表示波动低点。

  • hh_ll: 最低低点或最高高点。

  • hh_ll_dt: 最高高点或最低低点的日期。

我们将使用列表推导式声明变量:

#### latest_swings(df, shi, slo, rt_hi, rt_lo, _h, _l, _c, _vol) ####
def latest_swing_variables(df, shi, slo, rt_hi, rt_lo, _h, _l, _c):
    '''
    Latest swings dates & values
    '''
    shi_dt = df.loc[pd.notnull(df[shi]), shi].index[-1]
    slo_dt = df.loc[pd.notnull(df[slo]), slo].index[-1]
    s_hi = df.loc[pd.notnull(df[shi]), shi][-1]
    s_lo = df.loc[pd.notnull(df[slo]), slo][-1]

    if slo_dt > shi_dt: 
        swg_var = [1,s_lo,slo_dt,rt_lo,shi, df.loc[slo_dt:,_h].max(), df.loc[slo_dt:, _h].idxmax()]         
    elif shi_dt > slo_dt: 
        swg_var = [-1,s_hi,shi_dt,rt_hi,slo, df.loc[shi_dt:, _l].min(),df.loc[shi_dt:, _l].idxmin()]        
    else: 
        ud = 0
    ud, bs, bs_dt, _rt, _swg, hh_ll, hh_ll_dt = [swg_var[h] for h in range(len(swg_var))]   

    return ud, bs, bs_dt, _rt, _swg, hh_ll, hh_ll_dt
#### latest_swings(df, shi, slo, rt_hi, rt_lo, _h, _l, _c, _vol) ####

ud,bs,bs_dt,_rt,_swg,hh_ll,hh_ll_dt = latest_swing_variables(df,shi,slo,rt_hi,rt_lo,_h,_l,_c)

ud, bs, bs_dt, _rt, _swg, hh_ll, hh_ll_dt 

这将产生如下输出:

(1,
 213.43,
 Timestamp('2020-03-23 00:00:00'),
 'Lo1',
 'Hi3',
 452.6,
 Timestamp('2021-09-02 00:00:00')) 

上面声明的变量将在接下来的小节中使用。

确定趋势耗尽

到目前为止我们所做的工作有两个目标。我们已经检测到历史波动并对其进行了清理。然后,我们声明了我们将用于实时查找最新波动的变量。我们用于检测最终波动的方法称为重新测试。在 SPY 图表的背景下,市场从波动低点打印出最高的高点。价格稍微下跌然后回升但未能达到最高高点。价格然后穿过了最高点低位。重新测试实质上是犹豫不决。它们非常频繁。市场往往会犹豫不决。然而,当重新测试发生在持续移动的末尾时,这可能表明趋势耗尽并且可能会逆转市场方向。

此距离测试充当过滤器。此函数有两个内置测试:

  1. 表示为波动的多个波动。我们使用*均真实范围ATR)或标准偏差的度量。

  2. 作为固定百分比的距离。

函数的默认设置是没有距离测试,这将返回实际上的通过。一个成功的测试要么是-1(对于波动低点),要么是+1(对于波动高点),以及 0(对于失败的测试)。我们还将定义一个计算 ATR 的函数。这是由传奇人物威尔斯·怀尔德最初创建的经典波动性度量:

#### test_distance(ud, bs, hh_ll, vlty, dist_vol, dist_pct) ####
def test_distance(ud,bs, hh_ll, dist_vol, dist_pct): 

    # priority: 1\. Vol 2\. pct 3\. dflt
    if (dist_vol > 0):    
        distance_test = np.sign(abs(hh_ll - bs) - dist_vol)
    elif (dist_pct > 0):
        distance_test = np.sign(abs(hh_ll / bs - 1) - dist_pct)
    else:
        distance_test = np.sign(dist_pct)

    return int(max(distance_test,0) * ud)
#### test_distance(ud, bs, hh_ll, vlty, dist_vol, dist_pct) ####
#### ATR ####
def average_true_range(df, _h, _l, _c, n):
    '''
    http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:average_true_range_atr
    '''
    atr =  (df[_h].combine(df[_c].shift(), max) - df[_l].combine(df[_c].shift(), min)).rolling(window=n).mean()
    return atr

#### ATR ####

dist_vol = round(average_true_range(df,_h,_l,_c,n=63)[hh_ll_dt] * 2,2)
dist_pct = 0.05
_sign = test_distance(ud,bs, hh_ll, dist_vol, dist_pct)
_sign 

这将产生以下输出:

1 

这个距离测试验证了最新波动到最极端价格之间的距离,无论是以波动单位还是百分比点表示,都足够大以表明潜在的趋势耗尽。这个过滤器减少了虚假信号的出现。

重新测试波动

所有函数都引导我们到了这一刻:波动检测。这个小函数有着出人意料的效果。对于波动的高点或低点逻辑是对称的。因此我们将集中在波动的高点上:

  1. 检测从波动低点到最高高点。

  2. 从最高高点开始,识别最高的重新测试低点。

  3. 当价格收盘低于最高的重新测试低点时:波动高点 = 最高高点。

此方法同样适用于识别波动的低点。序列的展开如下:

  1. 检测从波动高点到最低低点。

  2. 从最低低点开始,识别最低的重新测试高点。

  3. 当价格收盘高于最低的重新测试高点时:波动低点 = 最低低点。

请注意,函数将始终重置为最高的重新测试低点。有时,价格会急剧下降,然后试图恢复一些镇定,只是后来失败了。当重置为最高的重新测试低点时,函数将毫不浪费时间地识别趋势可能已经逆转的最早时刻。

该函数还会创建系列rt(绝对值)或rrt(相对值),以显示用于检测波动的重新测试。如果你想可视化哪个重新测试被用于检测波动,这个可选功能可能会有用。

图 5.14中,这是黑点:

#### retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg) ####
def retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg):
    rt_sgmt = df.loc[hh_ll_dt:, _rt] 

    if (rt_sgmt.count() > 0) & (_sign != 0): # Retests exist and distance test met    
        if _sign == 1: # 
            rt_list = [rt_sgmt.idxmax(),rt_sgmt.max(),df.loc[rt_sgmt.idxmax():, _c].cummin()]

        elif _sign == -1:
            rt_list = [rt_sgmt.idxmin(), rt_sgmt.min(), df.loc[rt_sgmt.idxmin():, _c].cummax()]
        rt_dt,rt_hurdle, rt_px = [rt_list[h] for h in range(len(rt_list))]

        if str(_c)[0] == 'r':
            df.loc[rt_dt,'rrt'] = rt_hurdle
        elif str(_c)[0] != 'r':
            df.loc[rt_dt,'rt'] = rt_hurdle    

        if (np.sign(rt_px - rt_hurdle) == - np.sign(_sign)).any():
            df.at[hh_ll_dt, _swg] = hh_ll 
    return df
#### retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg) ####

df = retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg)
try:
    df['rt '] = df['rt'].fillna(method='ffill')
    df[bs_dt:][[_c, rt_hi, rt_lo,
        shi, slo,'rt']].plot(style=['grey', 'c.','y.',
        'rv', 'g^', 'ko'],figsize=(20,5),grid=True, title = str.upper(ticker))
except:
    df[bs_dt:][[_c, rt_hi, rt_lo,
        shi, slo]].plot(style=['grey', 'c.','y.',
        'rv', 'g^', 'ko'],figsize=(20,5),grid=True, title = str.upper(ticker)) 

在结果图表的最后一个黑点是最高的重新测试低点。请注意,当函数遇到新的高点或新的低点时会重置,因此如果运行函数时看不到它,不必担心。

图 5.14:从波动低点重新测试

只要价格持续创造新的高点,重新测试就会一路重置。途中会有虚假的信号,但这是旅程的一部分。

一些读者可能不同意重新测试的方法,无论原因是什么。因此,我们介绍了一种替代的波动检测方法。

回撤波动

这个函数是重新测试方法的一种替代。它完全依赖于从极值的回撤。这种方法的主要优点是概念上的简单性。一旦价格朝着相反的方向移动足够远,通常可以安全地得出波动已经出现的结论。然而,这个工具是比较直接的。它通常有效,但在横盘或者波动性很大的市场中失败:

  1. 计算从极值到极值的回撤,即从顶部的最小值或底部的最大值。

  2. 距离测试以波动率单位或百分点计算。

这个函数在重测不及时出现时充当救命稻草:

#### retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct) 
def retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct):
    if _sign == 1: #
        retracement = df.loc[hh_ll_dt:, _c].min() - hh_ll

#### removed for brevity: check GitHub repo for full code ####
#### retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct) ####

vlty = round(average_true_range(df=df, _h= _h, _l= _l, _c= _c , n=63)[hh_ll_dt],2)
dist_vol = 5 * vlty
dist_pct = 0.05
_sign = test_distance(ud,bs, hh_ll, dist_vol, dist_pct)
df = retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg)
retrace_vol = 2.5 * vlty
retrace_pct = 0.05
df = retracement_swing(df,_sign,_swg,_c,hh_ll_dt,hh_ll, vlty,retrace_vol, retrace_pct)

df[[_c,_hi,_lo,shi,slo]].plot(
    style=['grey','r.', 'g.', 'rv', 'g^'],
    figsize=(20,5),grid=True, title = str.upper(ticker))

df[[_c,shi,slo]].plot(style=['grey','rv', 'g^'],
            figsize=(20,5),grid=True, title = str.upper(ticker)) 

这创建了以下图形:

图 5.15:回撤摆动函数等级 2 和 3

图 5.16:回撤摆动函数摆动高点和低点

这个最终函数在市场剧烈波动时起到了救命稻草的作用。两个函数(retest 和 retracement)可以同时使用。

因此,我们经历了所有这些冗长的代码,得出了一些有意义的数据点,称为摆动高点低点。接下来,我们将使用这些摆动作为制度检测的依据。

将所有内容汇总:制度检测

让我们通过所有功能进行快速回顾。为了展示功能的多样性,我们将稍微调整一下事物。首先,我们再次发布相对函数的代码。然后,我们将在绝对情况下运行 SPY,然后将其与 ONEQ(纳斯达克的代理 ETF)进行比较。

我们将绘制三个图表,显示最佳配置资金的位置:

### RELATIVE
def relative(df,_o,_h,_l,_c, bm_df, bm_col, ccy_df, ccy_col, dgt, start, end,rebase=True):
    '''
    df: df
    bm_df, bm_col: df benchmark dataframe & column name
    ccy_df,ccy_col: currency dataframe & column name
    dgt: rounding decimal
    start/end: string or offset
    rebase: boolean rebase to beginning or continuous series
    '''
#### removed for brevity: check GitHub repo for full code ####
### RELATIVE ###
bm_df = pd.DataFrame()
bm_col = 'ONEQ'
ccy_col = 'USD'
dgt= 3
bm_df[bm_col] = round(yf.download(tickers= bm_col,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None)['Close'],2)
bm_df[ccy_col] = 1

df = raw_data.copy()
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
rhs = ['Hi1', 'Lo1','Hi2', 'Lo2', 'Hi3', 'Lo3']
rt_hi,rt_lo,_hi,_lo,shi,slo = [rhs[h] for h in range(len(rhs))]
df= relative(df,_o,_h,_l,_c, bm_df, bm_col, ccy_df=bm_df, 
            ccy_col=ccy_col, dgt= dgt, start=start, end= end,rebase=True)

for a in np.arange(0,2):  
    df = historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None)
    df = cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo)
    ud, bs, bs_dt, _rt, _swg, hh_ll, hh_ll_dt = latest_swing_variables(df, shi, slo,rt_hi,rt_lo,_h, _l,_c)
    vlty = round(average_true_range(df=df, _h= _h, _l= _l, _c= _c , n=63)[hh_ll_dt],2)
    dist_vol = 5 * vlty
    dist_pct = 0.05
    _sign = test_distance(ud,bs, hh_ll, dist_vol, dist_pct)
    df = retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg)
    retrace_vol = 2.5 * vlty
    retrace_pct = 0.05
    df = retracement_swing(df,_sign,_swg,_c,hh_ll_dt,hh_ll, vlty,retrace_vol, retrace_pct)
    rohlc = ['rOpen','rHigh','rLow','rClose']
    _o,_h,_l,_c = [rohlc[h] for h in range(len(rohlc)) ]
    rrhs = ['rH1', 'rL1','rH2', 'rL2', 'rH3', 'rL3']
    rt_hi,rt_lo,_hi,_lo,shi,slo = [rrhs[h] for h in range(len(rrhs))] 

让我们来看看此代码涉及的关键步骤:

  1. 我们实例化基准 ONEQ。货币是 USD

  2. 我们通过复制原始数据来实例化 df。我们运行两个列表推导式来声明变量。

  3. 我们运行相对函数以获取相对价格。

  4. for 循环将在绝对系列上运行一次。在第一次运行结束时,我们运行两个列表推导式来声明相对变量。

  5. 在第二个循环中,绝对变量被相对变量替换。一切都是对称的。参数保持不变。唯一改变的是输入系列。

最后,我们打印四张图表:

df[['Close','Hi1','Lo1','Hi2','Lo2','Hi3','Lo3']].plot(style=['grey','y.', 'c.','r.', 'g.', 'rv', 'g^'],
    figsize=(20,5),grid=True, title = str.upper(ticker))
df[['Close','Hi3','Lo3']].plot(
    style=['grey', 'rv', 'g^'],
    figsize=(20,5),grid=True, title = str.upper(ticker))

df[['Close','Hi3','Lo3',_c,shi,slo]].plot(
    style=['grey','rv', 'g^','k:','mv','b^'],
            figsize=(20,5),grid=True, title = str.upper(ticker)+' vs '+str.upper(bm_col))
rohlc = ['rOpen','rHigh','rLow','rClose']
_o,_h,_l,_c = [rohlc[h] for h in range(len(rohlc)) ]

df[[_c,shi,slo]].plot(
    style=['k:','mv','b^'],
            figsize=(20,5),grid=True, title = str.upper(ticker)+' vs '+str.upper(bm_col)) 

第一个是圣诞树状的图表,有很多小点:

图 5.17:带有高/低等级 1 到 3 的 SPY

所有信息都在。图表很杂乱。第二个是一个干净的 SPY 图表:

图 5.18:带有摆动高点和低点的 SPY

这是一张干净的 SPY 图表。误报已被清除。现在是时候进行大结局了;SPY 对比 ONEQ

图 5.19:SPY 的绝对和相对 ONEQ

SPY 明显表现不及 ONEQ,这意味着标准普尔 500 指数连续几年表现不及纳斯达克。相对价值的波动往往与绝对价值的波动相呼应。有趣的是,看第四张也是最后一张图表,似乎相对价值已经触底,意味着最后的摆动低点似乎明显高于最低点:

图 5.20:SPY 是否最终触底对 ONEQ?

当我们打印相对图表时,似乎最后一个波动低点可能要高于最低点。这意味着相对图表可能已经触底。这可能是标普 500 可能开始跑赢纳斯达克的早期迹象。这很好地引导我们进入下一节关于地板/天花板制度定义的内容。

制度定义

熊市在新低显著高于最低点时结束。在某一点上,市场将会出现底部。随后的每一个低点都会定格得更高。将所有低点与底部进行比较。一旦以波动调整单位或甚至百分点来表达的距离足够宽,市场就找到了一个支撑。在执行交易员的英文中,如果所有卖方的悲观情绪都无法突破最低点,那么市场就不再是熊市。

牛市在所有涨势都回落到顶部以下时结束。在某一点上,市场将会出现顶部。如果每次后续的涨势都在顶部以下落定,市场就找到了天花板。在执行交易员的英文中,如果所有的看涨情绪都无法达到高点,那么这个牛市就结束了。当找到天花板时,市场可能会转为横盘或熊市。相反,当找到地板时,市场可能会转为横盘或牛市。

公式是从峰值/谷底到随后波动高点/低点的距离的z-分数。z-分数是以波动性单位(ATR、标准偏差、已实现或隐含)表示的增量。下面的代码可能看起来有点冗长。然而,原则上是概念上简单的。

经典的牛市制度定义如下:

  1. 寻找天花板:搜索窗口从地板开始。

  2. 测量当前波动与天花板的距离:ceiling_test = (swing_high[i]-top)/stdev[i]

  3. 如果到天花板的距离小于x个标准偏差,那么制度已经转为熊市。

经典的熊市制度定义如下:

  1. 寻找地板:搜索窗口从天花板开始。

  2. 测量当前波动与底部的距离:floor_test = (swing_low[i]-bottom)/stdev[i]

  3. 如果到地板的距离大于x个标准偏差,那么制度已经转为牛市。

地板/天花板函数的代码是本章的精华部分。该函数如下:

#### regime_floor_ceiling(df, hi,lo,cl, slo, shi,flr,clg,rg,rg_ch,stdev,threshold) ####
def regime_floor_ceiling(df, _h,_l,_c,slo, shi,flr,clg,rg,rg_ch,stdev,threshold):
    # Lists instantiation
    threshold_test,rg_ch_ix_list,rg_ch_list = [],[], []
    floor_ix_list, floor_list, ceiling_ix_list, ceiling_list = [],[],[],[]

    ### Range initialisation to 1st swing
    floor_ix_list.append(df.index[0])
    ceiling_ix_list.append(df.index[0])

    ### Boolean variables
    ceiling_found = floor_found = breakdown = breakout = False

    ### Swings lists
    swing_highs = list(df[pd.notnull(df[shi])][shi])
    swing_highs_ix = list(df[pd.notnull(df[shi])].index)
    swing_lows = list(df[pd.notnull(df[slo])][slo])
    swing_lows_ix = list(df[pd.notnull(df[slo])].index)
    loop_size = np.maximum(len(swing_highs),len(swing_lows))

    ### Loop through swings
    for i in range(loop_size): 

        ### asymetric swing list: default to last swing if shorter list
#### removed for brevity: check GitHub repo for full code ####

         ### CLASSIC CEILING DISCOVERY
#### removed for brevity: check GitHub repo for full code ####

        ### EXCEPTION HANDLING: price penetrates discovery swing
#### removed for brevity: check GitHub repo for full code ####
        ### CLASSIC FLOOR DISCOVERY        
#### removed for brevity: check GitHub repo for full code ####

        ### EXCEPTION HANDLING: price penetrates discovery swing
#### removed for brevity: check GitHub repo for full code #### 
    ### POPULATE FLOOR,CEILING, RG CHANGE COLUMNS
#### removed for brevity: check GitHub repo for full code ####

#### regime_floor_ceiling(df, hi,lo,cl, slo, shi,flr,clg,rg,rg_ch,stdev,threshold) ####
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
rg_val = ['Hi3','Lo3','flr','clg','rg','rg_ch',1.5]
slo, shi,flr,clg,rg,rg_ch,threshold = [rg_val[s] for s in range(len(rg_val))]
stdev = df[_c].rolling(63).std(ddof=0)
df = regime_floor_ceiling(df,_h,_l,_c,slo, shi,flr,clg,rg,rg_ch,stdev,threshold)

df[[_c,'Hi3', 'Lo3','clg','flr','rg_ch','rg']].plot(    style=['grey', 'ro', 'go', 'kv', 'k^','c:','y-.'],     secondary_y= ['rg'],figsize=(20,5),    grid=True, title = str.upper(ticker)) 

在这个令人生畏的冗长代码背后是简单的逻辑。让我们来看看它的主要表达。基本上有两种逻辑:

  1. 经典地板和天花板发现:我们循环遍历波动,以识别高点和随后下降的波动高点,以及低点和上升的波动低点。这种设置在代码内部被称为经典地板和天花板发现。

  2. 异常处理:当价格穿透发现波动时发生:

    • 初始穿透:对于地板,我们寻找自发现波动低点以来的最低点。对于天花板,我们寻找自发现波动高点以来的最高点。制度被重置为以前的主导制度。

    • 回归:有时价格会反弹。这种来回异常处理确保了制度对随机性的良好响应。

  3. 循环结束后,列将被填充。

在做出这些澄清之后,啊哈!地板/天花板制度是次要* y *轴上的虚线水*线。这种制度方法是稳定的定义:

图 5.21:SPY 收盘价和地板/天花板看涨制度

制度在整个时期内保持看涨状态。市场“遇到了一个软弱期”,在 2020 年初。制度甚至没有眨眼。这并不意味着这种制度定义没有响应。这并不意味着市场参与者应该“买了就盼望”。这只是制度没有改变。这种稳定性使市场参与者能够以冷静、镇定的方式表达策略并管理风险。

方法比较

“学会选择是困难的。学会做出好选择更困难。而在一个选择无限可能性的世界中学会做出好选择更加困难。”

– 巴里·施瓦茨关于选择悖论的看法

2004 年,巴里·施瓦茨用我们一直以来直觉感受到的事情震惊了世界。我们已经概述了一些方法。让我们用图形方式进行比较,并希望赢家会在视觉上脱颖而出。

首先,让我们单独打印地板/天花板。小点是一级。大点是二级。黑色三角形是地板。阴影是制度的长度。它从第一个摆动低点开始一直延伸到右边。即使是大流行的“软弱期”也没有对此造成影响。这是尽可能稳定的:

图 5.22:SPY 地板/天花板看涨制度永远

这可能被认为对市场的波动没有响应,而在某种程度上确实如此。在 2020 年第一季度,世界似乎正在以 AC/DC 的谚语“通往地狱的高速公路”为目标。然而,这种制度并没有动摇。它可能在 2020 年 5 月底的上升期间闪烁着熊市的迹象,但很快又恢复成罗伯特·德尼罗式的“暴牛”市场。这既不是好事也不是坏事。这只是这种制度方法的运作方式。绝大多数市场参与者都是长期的趋势追随者。他们想要购买的东西,是要将来与他们的菲利普·帕特克手表收藏一起传给子孙后代的。

这并不意味着他们在接下来的十年里什么都不做。市场参与者经常在市场崩盘时加仓,这被称为弱势买入。这是实现这一完美制度定义方法的绝佳途径。这种制度检测方法的无与伦比的稳定性为长期背景环境设定了基调。制度要么是看涨的,要么是看跌的。然后,市场参与者可以根据主导制度叠加各种策略,无论是“在弱势买入”还是“在强势卖出”。

更重要的是,沃伦·巴菲特说过,当街上流血时我们应该买入。当市场像石头一样下跌,我们的边缘脑感到困惑时,这并不容易做到。这就是这种制度方法带来的所需的安心感,以便采取行动。

其次,我们打印出移动*均和范围突破的制度方法:

ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
mav = [20, 50, 200]
ma_st,ma_mt,ma_lt = [df[_c].rolling(mav[t]).mean() for t in range(len(mav))]

bo = [50, 252]
st_lo,lt_lo = [df[_l].rolling(bo[t]).min() for t in range(len(bo))]
st_hi,lt_hi = [df[_h].rolling(bo[t]).max() for t in range(len(bo))]

rg=lo=hi=slo=shi=clg=flr=rg_ch = None
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi)

rg_combo = ['Close','rg','Lo3','Hi3','Lo3','Hi3','clg','flr','rg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch =[rg_combo[r] for r in range(len(rg_combo)) ]

graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

这将产生以下两个图表:

图 5.23:SPY 制度突破和移动*均线交叉

变量故意比普通市场参与者的耐心长得多。范围突破设置为 252 天突破和 50 天止损。三重移动*均线具有著名的黄金交叉和 20 天入场/出场。这些变量是故意校准的,用于长期趋势。它们不应像参议员那样来回摇摆。然而,在路上还是有一些变化。

第二个图表叠加了地板/天花板方法。这是从第一个波动到图表结束的最浅的蓝色:

图 5.24:SPY 地板/天花板、突破和移动*均线交叉制度

上述图表将所有三种方法结合在一个简洁的可视化中。地板/天花板是最浅的蓝色。请注意,地板/天花板制度优先于所有其他方法。除非地板/天花板制度改变,否则使用范围突破或移动*均线交叉方法的看跌阶段不会反映出来。

最重要的一点是,地板/天花板方法提供了建立策略的稳定基础。知道市场仍然看涨并且应该买入低点有巨大的价值。其他任何方法都不提供这种稳定水*。机构投资者进行大额交易。进出会侵蚀盈利能力。这就是为什么他们会重视稳定性而不是准确性。当条件改变时,他们改变主意。在那之前,这是正常的戏剧。市场参与者可以根据自己的意愿制定策略。它可以是波动检测、移动*均线、范围突破或风险反转。唯一重要的是知道市场仍然处于看涨领域。

对于更喜欢行动而不是耐心的市场参与者,有两种方法可以加速地板/天花板方法。它依赖于波动。增加波动次数,制度就会机械地更紧张。

  • 方法 1:使用 2 级而不是 3 级波动。3 级过滤掉很多噪音。这也使其不太敏感。如果你不介意噪音,就继续

  • 方法 2:更快的周期性。这些数据是在日间柱状图时间段上处理的。保持相同的三级别,但将周期性加速到 4 小时。这第二种方法给出了一些迷人的结果。尝试以 1-5 分钟的间隔下载数据。处理摆动检测序列,并观察分形图在日间柱状图上绘制出几乎完美的图像。警告:这种方法对历史数据效果很好,但会产生大量错误的正面结果。因此,我们没有生成数据来推广这种方法

上述股票是做多的一个例子。在一本关于卖空的书中看起来有点不协调。然而,来自多头的市场参与者更容易传达这个信息。这种方法在卖空方面严谨对称。因此,现在是重新审视我们所钟爱的富国银行例子的时候了。我们将在绝对和相对于标普 500 的情况下运行该序列,并发布相应的图表:

params = ['2014-12-31', None, 63, 0.05, 0.05, 1.5, 2]
start, end, vlty_n,dist_pct,retrace_pct,threshold,dgt= [params[h] for h in range(len(params))]

rel_var = ['^GSPC','SP500', 'USD']
bm_ticker, bm_col, ccy_col = [rel_var[h] for h in range(len(rel_var))]
bm_df = pd.DataFrame()
bm_df[bm_col] = round(yf.download(tickers= bm_ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None)['Close'],dgt)
bm_df[ccy_col] = 1

ticker = 'WFC'
df = round(yf.download(tickers= ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None),2)
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
df= relative(df=df,_o=_o,_h=_h,_l=_l,_c=_c, bm_df=bm_df, bm_col= bm_col, ccy_df=bm_df, 
            ccy_col=ccy_col, dgt= dgt, start=start, end= end,rebase=True)

df[['Close','rClose']].plot(figsize=(20,5),style=['k','grey'],
                           title = str.upper(ticker)+ ' Relative & Absolute') 

这将生成如下图表:

图 5.25:富国银行绝对和相对于标普 500 的情况

上述代码是我们在前面章节已经见过的重复内容。接下来,我们将运行该序列。值得注意的一点是,关于基准和货币的计算优先于单只股票的计算。如果您想在整个投资范围内运行相同的计算,只需插入一个循环以迭代股票代码。

接下来,我们将摆动检测和制度定义运行两次。首先,我们在绝对系列上运行它。在循环结束时,我们将变量重新初始化为相对系列。然后我们在相对系列上运行序列:

swing_val = ['rg','Lo1','Hi1','Lo3','Hi3','clg','flr','rg_ch']
rg,rt_lo,rt_hi,slo,shi,clg,flr,rg_ch = [swing_val[s] for s in range(len(swing_val))]

for a in np.arange(0,2):    
    df = round(historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None),2)
    df = cleanup_latest_swing(df,shi,slo,rt_hi,rt_lo)
    ud, bs, bs_dt, _rt, _swg, hh_ll, hh_ll_dt = latest_swing_variables(df, 
            shi,slo,rt_hi,rt_lo,_h,_l, _c)
    vlty = round(average_true_range(df,_h,_l,_c, n= vlty_n)[hh_ll_dt],2)
    dist_vol = 5 * vlty
    _sign = test_distance(ud,bs, hh_ll, dist_vol, dist_pct)
    df = retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg)
    retrace_vol = 2.5 * vlty
    df = retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct)
    stdev = df[_c].rolling(vlty_n).std(ddof=0)
    df = regime_floor_ceiling(df,_h,_l,_c,slo, shi,flr,clg,rg,rg_ch,stdev,threshold)    

    rohlc = ['rOpen','rHigh','rLow','rClose']
    _o,_h,_l,_c = [rohlc[h] for h in range(len(rohlc)) ]
    rswing_val = ['rrg','rL1','rH1','rL3','rH3','rclg','rflr','rrg_ch']
    rg,rt_lo,rt_hi,slo,shi,clg,flr,rg_ch = [rswing_val[s] for s in range(len(rswing_val))] 

我们之前已经解释了所有这些功能。现在,序列被打包在一个代码块中。在附录中,我们将以更加优雅的方式重新打包这一点,使用一个函数。最后,我们打印色彩缤纷的图表,以表示绝对和相对的制度:

ma_st = ma_mt = ma_lt = lt_lo = lt_hi = st_lo = st_hi = 0

rg_combo = ['Close','rg','Lo3','Hi3','Lo3','Hi3','clg','flr','rg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch =[rg_combo[r] for r in range(len(rg_combo)) ]
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi)

rrg_combo = ['rClose','rrg','rL3','rH3','rL3','rH3','rclg','rflr','rrg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch =[rrg_combo[r] for r in range(len(rrg_combo)) ]
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

所有其他参数都已经静音。代码将打印两个图表。我们只想查看绝对和相对的地板/天花板制度。首先,我们将打印绝对系列:

图 5.26:富国银行的绝对地板/天花板制度

这张图是一个很好的例子,因为它显示了这个制度并不是万能的。地板/天花板方法并不是对随机性的通用治疗方法。在多头阶段有亏损期。这意味着制度定义并不能替代风险管理。接下来,我们打印富国银行相对于标普 500 的情况:

图 5.27:富国银行相对于标普 500 的地板/天花板制度

再次强调,富国银行并非长期表现不佳。它有着短暂的辉煌时刻,在夕阳下“升起和闪耀”,然后再次滑入漫长的下降。正如最后一个摆动低点所示,制度甚至可能已经转为看涨。也许这一次,超额表现可能更具可持续性。

在底部或顶部后时间最佳入场点的时机

“投资者为了修正,或试图预测修正而损失的资金远远超过了修正本身的损失。”

– 彼得·林奇

第一个问题是,想要通过预期体制变化来保护自己收益的市场参与者长期来看往往会亏钱。如果有一位“专家”走到你面前说:“你下周会生病。你将生病三个月。你将在这一天痊愈。”你可能会觉得他们已经丢失了 L 码的锡箔帽子!

然而,在市场上,我们注意到这种不断的“金钱狂欢”(记住我们在第二章中的关键字,“关于做空的 10 个经典神话”)。市场大师擅长顶部和底部的时机。事实上,他们已经 39 次无误地掌握了最*的 2 次熊市!然而,预测顶部和底部是愚人的游戏。在底部和顶部之间有成千上万的日子。你可以错过头 50 天,仍然能抓住大行情。地板/天花板方法不会在顶峰时让你离场。它将以合理的准确度使你在可能的最高点进入空头头寸。

看穿基本新闻流

第二个问题出现在基本新闻流跟上市场走势时。基本信息在市场顶部看起来强劲,在市场底部看起来疲软。它报告过去的数字,如月销售额、订单等。与此同时,市场往往是前瞻性的。市场参与者会陷入“确认偏见”:他们已经拥有了他们需要加倍头寸或放弃的所有基本证据。

这种地板和天花板方法是一种客观的评估是否是时候保持乐观态度还是采取更为防御性立场的方式。这种方法有几个优点。首先,稳定性带来可靠性。例如,自 2008 年危机爆发以来的十多年里,标普 500 指数的体制只在两次转变为多头至横盘熊市。每次,不到 3 个月后,体制就恢复为多头。

将此与价格在 200 日移动*均线附*翻转了 20 多次的情况相比。这种稳定水*为市场参与者带来了更高的信心。在体制改变之前,每次回调都是一个买入机会。

这种方法还带来了清晰度。它让我们免受我们的理性愚蠢之苦。在某些时候,我们都遇到过一支股票,我们认为:“这个涨得太多了,是时候做空了。”嗯,这往往发生在多头体制的股票上。或者,我们可能会说:“这跌得太多了,是时候买入了。”这也往往发生在熊市股票上。体制带来了清晰度:买入多头并对冲,卖出空头并对冲。

识别转折点

地板/天花板方法的优势在于转折点。我们长期以来认为,牛市需要结束才能开始熊市,反之亦然。通过这种方法,熊市在牛市结束时开始,反之亦然。其中的微妙之处是昂贵的。它允许市场参与者在一个制度过渡到下一个制度时定位自己。

兴奋的市场参与者常常在顶峰过后仍保持乐观,而在谷底过后仍感沮丧。在我们左右耳垂之间的尖叫声中,我们常常无法听到市场悄悄地低语。

最难确定的是何时清算盈利头寸。这种方法足够强大,可以让尤利西斯系在理性的桅杆上,越过市场的塞壬。好消息是,这种方法在逻辑上是准确的。熊市在新的进展回落到地板以下时开始。牛市在新的低点保持在天花板以上时开始。

让市场制度决定最佳策略。

“当你排除了一切不可能的情况,那么无论剩下的是多么不可能,都必须是真相。”

——阿瑟·柯南·道尔

多年来,我逐渐相信绩效的两个主要决定因素是头寸规模和市场制度。交易过大可能会让你破产。交易过小则没有生意可做。其次,经验丰富的市场参与者通常有几种策略来应对不同的市场类型。

困难在于何时使用哪种策略,更重要的是何时淡化它们。这归结于制度的定义。地板/天花板方法可能会改变你交易市场的方式。

有两种类型的策略:均值回归和趋势跟踪。均值回归在范围限定的市场中效果最好。价格以一种半可预测的方式围绕均值波动。均值回归策略在趋势市场中表现不佳。趋势跟踪策略在牛市或熊市中表现良好,但在横向市场中会失去收益。

在牛市结束时,当找到天花板时,市场可以横向或熊。并非所有的夏季牛市者都会在同一天醒来穿上他们的冬季熊市服装。假设市场将会横向运行,直到“黄金交易者”(那些智商比黄金还要厚重的落后者)意识到熊市占据主导地位。相反,当找到地板时,需要时间来处理熊市的创伤经历,并为新生的牛市做好定位。

一旦找到地板或天花板,假设市场会横向运行,或者在一个范围内交易,直到有证据表明它走向熊市或恢复其牛市趋势。暂停趋势交易,开始均值回归。一旦有证据表明新的趋势出现,并且市场创出低点/高点或突破范围,重新激活趋势交易,暂停均值回归。

对于长期持有者来说,对称通常是一个陌生的概念。市场参与者都以对称为理想出发,但很快意识到他们的多头规则在空头方面表现不佳。毕竟,多头方向行动缓慢且通常安静,而空头方向则快节奏且易变。然后,他们开始制定两套规则,分别应对每一方。通常,这在两个规则同时有效且股票可能是多头或空头的最糟糕的时候发生。这通常发生在最糟糕的时候:当绩效开始下降时。绩效下降不利于清晰思考。在这一点上,市场参与者倾向于坚定信念、故事或复杂的风险管理。对称避免了冲突的规则。它要么是多头,要么是空头,绝不会两者兼而有之。

让市场制度决定策略。地板/天花板方法为每个制度变化提供了客观的起点和终点:天花板、范围和地板。一旦你知道更广泛的制度应该是看涨、看跌还是横盘,就更容易设计适合每个篮子的策略。通过正确的制度定义和头寸大小,即使是一种*庸的策略也可以有积极的优势。

总结

我们已经研究了几种市场制度方法,这些方法将帮助你捕捉到市场上升或下降的信号。制度突破和移动*均线交叉是趋势跟踪交易员工具箱中的基本工具。持续时间与风格一样重要,就像市场恰好奖励的内容一样。然后,我们介绍了地板/天花板方法。这种制度定义方法适用于绝对和相对系列。它是对称的,最重要的是比任何其他方法更稳定。因此,它超越了一切。

然而,制度定义方法并不是互斥的。例如,地板/天花板方法可以用于确定交易的方向,多头或空头。然后,制度突破可以用于在整理或横盘市场后进入。最后,移动*均线交叉可以用于退出持仓。

有信号是一回事。将其转化为具有强大统计优势的盈利策略是另一回事。在卖空方面没有盈利等价物的"买入并持有"心态。卖空就像综合格斗。那个腰带会索取一部分代价。因此,我们将在第二部分,外部游戏:打造强大的交易优势中的其余时间里努力实现这一目标;建立强大的交易优势。

第六章:交易边缘是一个数字,这就是公式

在本章中,我们将揭开金融行业中最深受保护的秘密之一:帷幕后面不是一个老人,而是一个简单的公式。然后,我们将这个公式分解为两个不同的模块:信号和资金管理。

在信号模块内,我们将探讨如何计时进入和退出,以及似乎提供交易优势的两种策略类型的特性;趋势跟随和均值回归。 在 第七章 改善您的交易优势 中我们将继续讨论这个问题,在 第八章 头寸规模:在资金管理模块中赚钱 中我们将更深入地涉及资金管理模块。

在这个过程中,我们将涵盖以下主题:

  • 导入库

  • 交易边缘公式:算术和几何增益期望

  • 交易优势不是一个故事

  • 无论资产类别如何,都只有两种策略

您可以通过以下链接访问本章中所有图片的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。 您还可以通过该书的 GitHub 存储库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

对于本章和本书的其余部分,我们将使用 pandasnumpyyfinancematplotlib 库。 所以,请记得先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt 

交易边缘公式

"信息不等于知识。"

– 阿尔伯特·爱因斯坦,专利职员

谁说科幻小说没有进入严肃的金融世界?问任何对冲基金经理关于他们的优势,你将进入一个反对企业阴谋、金融福尔摩斯耐心地拼凑信息拼图的十字军世界,以及投资于下一个新的[插入下一个颠覆性技术热词……]的远见者。

交易业务中的每个人都会说你需要一种优势才能赚钱。然而,他们永远不会告诉你如何建立一个可持续的优势,可能是因为担心传播会侵蚀他们的优势。可以理解的是,交易优势一直是这种神秘的秘密调味品。

只有三种常见的边缘类型:技术、信息和统计,在接下来的几节中将被考虑。

技术优势

今天,任何零售交易者都可以获取比任何顶级机构投资者在 10 年前更多的信息和计算能力。任何有一点 Python 技能的人都可以从互联网上爬取数据,并通过机器学习或人工智能更快地处理它,比任何传统研究部门都快。一个与对冲基金级别相当的云基础设施成本不到 50 美元每月。任何人都可以免费在 YouTube、Quora 或任何其他学习*台上学习如何编码、分析数据、交易、投资和管理投资组合。技术已经将民主带入了金融世界。

每个人都想成为吉姆·西蒙斯,但没有人想管管道。正如图 6.1所示,当被问及程序化交易者面临的头号问题时,有三分之一的回答涉及数据处理和存储以及服务器管理。这表明,对于许多有抱负的算法交易者来说,主要障碍仍然是技术,他们需要一个完整的工程团队来自动化他们的交易。市场参与者需要成为专业的系统工程师,以确保持续的连接性。然后,他们必须提高他们的开发技能,编写不仅机器能够读懂,而且更重要的是人类能够读懂的代码。

图 6.1:交易自动化的瓶颈:对于许多有抱负的算法交易者来说,主要障碍仍然是技术

策略的第一次迭代就像困住米开朗基罗的大卫的石头。需要耐心的雕刻才能显现少年形象。写得不好时,解开另一个意大利文化遗产——意大利面的时间要更长。在这一切得到解决之后,市场参与者最终可以专注于设计产生阿尔法的策略。然后出现了另一套难题:缩放进出、风险管理,这本书涵盖了所有有趣的内容。将亿万美元的想法转化为无错代码仍然是一道艰巨的技术障碍。底线是,要让钱为你工作需要付出巨大的努力。

一个简单的类比可以是 Apple 1 时代的个人电脑行业。每个人都想玩太空入侵。只有极少数人愿意自己组装计算机来玩游戏。今天,每个比特币爱好者都想学习算法交易。很少有人愿意付出汗水、鲜血和泪水来建立自己的*台。这本书将为您提供构建自己策略的基础。

信息优势

该行业传统上一直认为信息能带来优势。这要么是特权信息,比如获得高层管理和分析师更好的对待,要么是它更阴险的表兄弟,内幕信息。任何信息优势都会很快被套利掉。

信息优势从来没有真正产生过影响。如果战胜街头所需的仅仅是更好的信息优势,那么理论上,拥有分析师议会、博士学位学校、基金经理的骄傲、交易员的谋杀、卖方研究员的漂移、经纪人的群体以及专家意见的万花筒的大型交易机构,通过速拨电话获得企业联系并有足够的资金来拯救半个大陆的能力,将会一直超越市场。实际上,尊崇的机构在记录中的每一年都远远落后于低科技、普通香草指数基金。信息只提供了一个随时间越来越快地被套利的暂时优势。信息希望被民主化。

统计优势

统计优势不容易被套利掉。它通过设计存在并持续存在。重要的不是你交易的“什么”,而是你交易的“如何”才重要。在接下来的章节中,我们将探讨构建强大的统计交易优势的方法。我们不会试图告诉你如何不同地挑选股票,而是如何从已经选择的股票中挤出更多的果汁。

交易边缘并非一个故事。

"如果你不能衡量它,你就不能改善它。"

– 彼得·德鲁克

交易边缘并非一个故事。交易边缘是一个数字,公式由几个函数组成:

  1. 算术增益期望:在执行交易员的英语中,这是你赢的次数乘以你*均赚多少减去你输的次数乘以你*均输多少。这个函数是经典的算术期望,存在于每一个初中统计学介绍中,却不在金融 MBA 中。当谈论交易优势或增益期望时,市场参与者默认使用算术增益期望。这个公式易于理解和计算。这个公式的简单性自然而然地占据了主导地位,即使对于那些不理解其复杂性的人也是如此。

    # Expectancy formula, win_rate is your Hit ratio, avg_win is the average gain per trade, and avg_loss is the average loss per trade
    def expectancy(win_rate, avg_win, avg_loss):
        # win% * avg_win% - loss% * abs(avg_loss%) 
        return win_rate * avg_win + (1-win_rate) * avg_loss 
    
  2. 几何增益期望(George):利润和损失以几何方式复利。几何增益期望在数学上更接*策略的预期稳健性。

    def george(win_rate,avg_win,avg_loss):  
        # (1+ avg_win%)** win% * (1- abs(avg_loss%)) ** loss%  -1 
        return (1+avg_win) ** win_rate * (1 + avg_loss) ** (1 - win_rate) - 1 
    
  3. 凯利准则是一种优化投资组合几何增长率的头寸大小算法。凯利具有引人入胜的历史,始于 18 世纪的数学家丹尼尔·伯努利,由 J.L.凯利 Jr.重新发现,并由传奇人物爱德华·索普推广。凯利使用与之前期望相同的成分,但做法略有不同。

    def kelly(win_rate,avg_win,avg_loss):  
        # Kelly = win% / abs(avg_loss%) - loss% / avg_win% 
        return win_rate / np.abs(avg_loss) - (1-win_rate) / avg_win 
    

在本章和下一章中,我们将使用一个基本策略来展示这些公式是如何工作的。把它看作是适用于白痴的海龟交易员。首先,我们重新利用 50/20 海龟策略来交易 Softbank(9984.T),不考虑滑点或交易成本。代码是从第五章制度定义中回收的。首先,我们重新定义一些函数。

def regime_breakout(df,_h,_l,window):
    hl =  np.where(df[_h] == df[_h].rolling(window).max(),1,
                                np.where(df[_l] == df[_l].rolling(window).min(), -1,np.nan))
    roll_hl = pd.Series(index= df.index, data= hl).fillna(method= 'ffill')
    return roll_hl

def turtle_trader(df, _h, _l, slow, fast):
    '''
    _slow: Long/Short direction
    _fast: trailing stop loss
    '''
    _slow = regime_breakout(df,_h,_l,window = slow)
    _fast = regime_breakout(df,_h,_l,window = fast)
    turtle = pd. Series(index= df.index, 
                        data = np.where(_slow == 1,np.where(_fast == 1,1,0), 
                                np.where(_slow == -1, np.where(_fast ==-1,-1,0),0)))
    return turtle 

然后我们通过白痴的海龟策略运行 Softbank,计算回报,并打印出两个图表。

ticker = '9984.T' # Softbank
start = '2017-12-31'
end = None
df =  round(yf.download(tickers= ticker,start= start, end = end, 
                        interval = "1d",group_by = 'column',
                        auto_adjust = True, prepost = True, 
                        treads = True, proxy = None),0)
slow = 50
fast = 20 
df['tt'] = turtle_trader(df, _h= 'High', _l= 'Low', slow= slow,fast= fast)
df['stop_loss'] = np.where(df['tt'] == 1, df['Low'].rolling(fast).min(),
                    np.where(df['tt'] == -1, df['High'].rolling(fast).max(),np.nan))

df['tt_chg1D'] = df['Close'].diff() * df['tt'].shift()
df['tt_PL_cum'] = df['tt_chg1D'].cumsum()

df['tt_returns'] = df['Close'].pct_change() * df['tt'].shift()
tt_log_returns = np.log(df['Close']/df['Close'].shift()) * df['tt'].shift()
df['tt_cumul'] = tt_log_returns.cumsum().apply(np.exp) - 1 

df[['Close','stop_loss','tt','tt_cumul']].plot(secondary_y=['tt','tt_cumul'],
                                  figsize=(20,8),style= ['k','r--','b:','b'],
                       title= str(ticker)+' Close Price, Turtle L/S entries, cumulative returns')

df[['tt_PL_cum','tt_chg1D']].plot(secondary_y=['tt_chg1D'],
                                  figsize=(20,8),style= ['b','c:'],
                                 title= str(ticker) +' Daily P&L & Cumulative P&L') 

代码执行以下步骤:

  1. 使用对数收益:对数收益比算术收益更易于处理。算术总数不会累积,而对数总数会。累积收益使用apply(np.exp)方法计算。

  2. 策略入/出场:使用shift()方法延迟一个柱来进行入场和出场。

下图显示了以黑色表示的收盘价和以红色虚线表示的移动止损。在次要轴上,我们有多空头寸:空头为-1,多头为+1。实线蓝色表示累积收益:

图 6.2:Dummy 的海龟:多头和空头进出场,累积收益

这个策略似乎在其原始格式下起效果。第二张图显示了每日和累积盈亏。*线表示没有活跃头寸时:

图 6.3:Softbank 每日及累积盈亏(P&L)

接下来,我们将计算滚动利润、损失和期望值,并将它们绘制成图表。

# Separate profits from losses
loss_roll = tt_log_returns.copy()
loss_roll[loss_roll > 0] = np.nan
win_roll = tt_log_returns.copy()
win_roll[win_roll < 0] = np.nan

# Calculate rolling win/loss rates and averages
window= 100
win_rate = win_roll.rolling(window).count() / window
loss_rate = loss_roll.rolling(window).count() / window
avg_win = win_roll.fillna(0).rolling(window).mean()
avg_loss = loss_roll.fillna(0).rolling(window).mean()

# Calculate expectancies
df['trading_edge'] = expectancy(win_rate,avg_win,avg_loss).fillna(method='ffill')
df['geometric_expectancy'] = george(win_rate,avg_win,avg_loss).fillna(method='ffill')
df['kelly'] = kelly(win_rate,avg_win,avg_loss).fillna(method='ffill')

df[window*2:][['trading_edge', 'geometric_expectancy', 'kelly']].plot(
    secondary_y = ['kelly'], figsize=(20,6),style=['b','y','g'], 
    title= 'trading_edge, geometric_expectancy, kelly') 
  1. 将每日收益复制到win_rollloss_roll中,使其具有统一长度的序列。将win_roll序列的损失值设为 N/A,将loss_roll序列的收益值设为反之。

  2. 实例化窗口大小和滚动计数以计算胜率和败率。

  3. 滚动求和方法不适用于缺失值。因此,我们使用fillna(0)方法将缺失值替换为0来计算移动*均值。填充数据框并绘图。

图 6.4:Softbank 滚动交易边缘,几何期望值,凯利

这个策略具有正的交易边缘,但请不要在家里尝试这个——它太简单,不能用于实际交易,仅供教育目的。图表上的这三条线是相同主题的变体。成分相同,但烹饪方式有点不同。关键是:直到盈利期望变为正数之前什么也不会发生。夏普比率、索提诺比率、詹森比率、特雷纳比率和信息比率都很好,但它们在盈利期望变为正数后才起作用。

所有这些公式都可以分解为两个模块:

  • 信号模块:胜率/败率。这些是由入场和出场信号生成的收益。

  • 资金管理模块:*均利润/亏损。这些是由投注大小乘以收益生成的贡献。

这揭开了交易优势的神秘面纱,将其视为可以从头开始设计的东西。市场参与者假装拥有未来的优越知识,归功于他们的分析超能力和机器学习水晶球。与此同时,赌场公开宣传随机性。然而,前者的回报是零散的,而后者每天都稳定盈利。这不是巧合。前者认为知识是一种优势,而赌场则设计他们的优势。因此,每个市场参与者的工作就是优化他们的交易优势。在接下来的几章中,我们将考虑如何设计这些模块并最大化交易优势,从信号模块开始,然后转向第八章中的资金管理模块和头寸大小的问题,头寸大小:财富创造于资金管理模块中

所以,话不多说,让我们开始信号模块。

信号模块:进场和出场

“你必须知道何时坚持,

知道何时放弃,

知道何时退缩,

也要知道何时退缩。”

– 肯尼·罗杰斯,《赌徒》

让我们从温和地打击一个古典神话开始:“只要你 51%的时间是正确的,你就会赚钱。”错了。按照他们自己的说法,行业顶尖表现者拥有数十年的业绩记录,通常声称长期的赢利率并不令人印象深刻。相反,LTCM 在 2000 年解散前自豪地宣称拥有异常高的赢利率。

只要你有一个积极的交易优势,你就能赚钱。我们需要设计的第一件事就是信号模块。正如我们在第一章中看到的,股票市场游戏,假阳性是无法根除的。随机性会一直存在。每个篮子里都有一些坏苹果。关键是设计政策来发现这些坏苹果,在它们破坏篮子之前处理它们,并继续前进。

进场:选股被高度高估了

“鞭打将继续,直到士气好转。”

– 布莱舰长,赏金号

股票市场是唯一一个人们喜欢在比赛开始之前颁发奖牌的竞技运动。这个行业是建立在股票选择者的崇拜之上的。每个人都喜欢谈论他们的最佳股票选择。90%的市场参与者的精力都集中在做出正确的决定上。不幸的是,同样 90%的市场参与者连续 5 年都无法击败他们的基准。

在量化交易员的行话中,这被称为相关性。当相关性在记录的每一年中持续存在时,即使只有一年,r-*方,量化术语中的因果关系,都会接* 1。在执行交易员的英语中,疯狂就是*均受挫的市场参与者将更多的精力和资源投入到选股中,然而年复一年地一直失败。总之,90%的市场参与者可预测地失败,因为他们一直专注于错误的事情:进场。也许是时候考虑采用不同的方法了。

根据杰里米·西格尔教授的说法,股市的长期*均回报率为+7%。这在空头方面留下了很少的空间来愉快交流。想法很廉价且充足。每个人都有一袋价值百万美元的想法。想法与利润之间的区别称为执行。正如我们在第一部分——内部游戏:解密空头交易中看到的那样,许多市场参与者在空头方面失败,因为他们是在想法萌芽时进入市场的,而不是在它们成熟可采摘时。表现不佳相当于我们吃未成熟水果时的消化不良。

本书不会给你提供银弹式的方法论。本书的目的是介绍市场的概率视角,以便你可以成为一个统计上更好的自己。这本书只是为你提供菜谱,用来处理你带到桌子上的材料。基本面、技术和量化空头都赚过钱,但他们在获得概率优势之前是不可能成功的。

有两个时机你需要注意概率:股票选择和进场。用执行交易员的术语来说,这意味着在扣动扳机之前有两个时机你应该听听市场的声音。

  • 首先,你需要卖空那些处于横盘或熊市阶段的股票。在牛市中做空股票就像站在铁轨上,期待一列又一列的货运火车停下来一样。在第五章,制度定义中,我们学会了根据它们的制度重新分类股票的客观方法。由于做空是一个相对的游戏(股票价格下跌绝对是一种落后的指标),制度变化经常以股票市场的部门轮换的形式出现。昨日的宠儿就是明日的狗。

  • 第二个需要关注概率的时机是进入市场。来自多方的市场参与者喜欢在突破时买入。但同样的逻辑在空头方面并不适用。请记住,几乎所有的市场参与者都在市场上做多。一些人一直在等待机会在市场低点买入。快速下跌的市场通常会紧随着迅速的熊市反弹。在短暂的时间内,概率会有利于空头。

    进入空头头寸的最佳时机是在熊市反弹结束时。我们将在第三部分——长/短游戏:打造长/短产品中详细讨论空头挤压的合气道。

我们之前看到了利润期望的可视化表示。在接下来的章节中,我们将研究旨在增加您交易优势的技术。它们不仅限于空头交易。有些可能不适用于你的风格或策略。

离场:纸上利润如何转化为真实资金

唯一会毫无退出策略地走入战场的士兵被称为神风特攻队士兵。他们不指望活着回来。因为你可能不指望你的交易看起来像自杀任务一样,所以制定退出策略的最佳时机是在你进入一个头寸之前,避免“被困住”。

在金融服务行业,比厕纸更便宜的只有回测和模拟打印输出。这只是纸上财富。没有人受到伤害。真正重要的是真金白银。让我们进一步思考这个观点。你唯一知道赚了多少“真钱”,或者亏了多少,是在交易关闭后。在那之前的一切都被称为纸面利润。底线是:退出很重要。

我们都被教导要相信我们的最初选择是最重要的。如果我们有正确的实习,从正确的大学毕业,或者选择了正确的第一份工作,那么我们的职业生涯将会一帆风顺。然而,生活就是当我们有其他计划时发生的事情。我们经常低估了运气在我们生活中的作用。在正确的时间出现在正确的地方让很多幸运的人变得富有。然而,这些人很少在第一次尝试时成功。他们尝试、失败,直到最后某件事情终于成功。

由于市场参与者喜欢买入并持有,婚姻可以说是一个合理的比喻。每段婚姻都以乐观的“从此过上幸福快乐的日子”开始,然而大约一半的婚姻最终以离婚告终。结婚很容易。离婚是一个改变人生的事件。如果在结婚前没有考虑到这一点,那么这将是情感和财务上的灾难。糟糕的婚姻可以挽救。糟糕的离婚不行。糟糕的进入可以挽救。糟糕的退出不行。这就是损益表被打印出来的时候。

你将会在接下来的章节中看到,提高你交易优势的 7 个步骤中,有 5 个与损失有关。另一个很好的类比是个人财务。你可以通过两种方式增加储蓄。要么你保持目前的开支并找份待遇更好的工作,要么你限制开支并节省差额。前者在你有稳定高薪时效果很好。

如果你的收入完全是变动的,那么你最明智的做法是保持低固定成本基础,并从市场中获得的差额放进口袋。你将获得与其他参与者一样的丰厚报酬,但不同的是你不需要它们来维持生计。在金融界的克里奥尔语中,这种对开支的关注被称为“及时止损”。

不论资产类别如何,只有两种策略

杰克·施瓦格经常指出并不存在普适的圣杯。市场巫师各式各样,有时甚至采取相互矛盾的策略。不过,他们有一个共同点。他们擅长管理风险和控制损失。他们始终关注下行风险。赢利头寸会自行处理。市场参与者的工作是处理失败者。

市场参与者通常通过他们交易的“什么”(资产类别、市场、时间跨度)来定义自己,而很少涉及到他们是以何种方式交易。无论资产类别如何,策略类型只有两种:趋势跟随和均值回归。只有两种策略的原因不是入场,而是出场。你如何选择结束一笔交易决定了你的主导交易风格。均值回归派在不效率得到纠正时就提前*仓。趋势跟随者喜欢乘胜追击。一个典型的例子是价值投资与成长投资。价值投资者购买低估股票,然后将接力棒交给成长投资者,由他们将股票持续走高。

例如,一个均值回归的市场参与者会以市净率PBR)为 0.5 的价格买入一只股票,当市净率回到 1 时*仓,然后离场。而趋势跟随者会以相同的估值买入同样的股票,但会一路持有至狂喜区域。他们最终会在这只曾经默默无闻、未被充分研究的股票被列入一流投资银行的“强力买入”列表后*仓,然后可预见地表现不佳。

一些读者可能会认为价值投资者更像是均值回归类型,而成长经理更像是趋势跟随类型。这通常是正确的,但并非总是如此。最好的反例,也可能是终极价值趋势跟随者,是沃伦·巴菲特。他投资于他打算永久持有的低估企业。你的头寸不是百达翡丽手表。你不会为未来的几代人持有它们。在某个时刻,你会*仓。只有三种可能:价格上涨、下跌或不变。你要么亏损、赚钱或浪费钱。你需要为每种情况制定一个方案。你需要一个计划来实现利润,减轻损失,并处理吃白食者。我们的目标是打造一个更好的统计交易优势。如果只有两种策略类型,那么花时间了解它们的行为方式、回报和风险,以及它们是否相互排斥或兼容,就显得非常重

趋势跟随

"财富在于坐等。"

– 杰西·利弗莫尔

趋势跟随策略依赖于少数几个大赢家的资本增值。系统化的商品交易顾问CTAs)寻找突破点并设定保护性的追踪止损。技术分析师寻找入场点并跟随上涨。即使是基本面股票选择者也算是趋势跟随者。他们不是关注价格走势,而是关注基本面改善、盈利势头,甚至是新闻流。归根结底,无论他们是否自觉承认,市场参与者的默认模式都是趋势跟随。由于趋势跟随是市场参与者的主导模式,我们在本书中使用了一种简单的趋势跟随策略(乌龟指标)。

这就是趋势跟随者的损益分布:

图 6.5:经典的趋势跟随多空盈亏分布

我们可以观察到以下特性:

  • 低胜率:在 30%到 50%之间。模式,交易的峰值数量,位于分布的亏损部分。对于每一家 Alphabet,Amazon 或 Apple,都有无数的 Nestcapes,Ataris 或 MySpaces。

  • Alpha 生成:趋势跟随策略依赖于少数赢家的资本增值来抵消众多小损失。这引入了利润随时间展开与损失迅速影响资产曲线之间的滞后。损失很快就会被处理,而赢家需要时间成熟。

  • 正偏斜:右尾盈亏分布给出了有利的尾部比率。赢家比输家要大。上述图表是古老格言“削减你的亏损,乘着你的赢家”的视觉表现。再次强调,要实现这些超额回报需要时间。与此同时,资产曲线必须处理沿途的蛙模糊。

  • 周期性:市场并不总是趋势性的。风格时而被青睐时而不受青睐。当一个风格不起作用时,损失开始累积。成功的趋势跟随者迅速意识到自己的错误,并使个别损失保持较小。当他们的风格受到青睐时,他们跟随趋势一直走到太阳落山处。

  • 相对较低的周转率:周转率是周期性的函数。当市场向上或向下趋势时,没有必要做任何事情。像传奇交易员杰西·利弗莫尔曾经说过的那样,钱是在坐着等待中赚的。当一种风格不受青睐时,周转率将增加,因为会有更多的蛙被搅动。

  • 波动性:这是周期性的结果。市场参与者经历了一段缺乏成效回报的时期。

趋势跟随者经常接触到很多蛙。风险在于所有美味蛙的累积模糊可能无法超过少数公主的公*性。趋势跟随策略的风险在于损失超过利润的总重量。

对于趋势跟随策略来说,最相关的风险度量是比较累积利润和损失。这就是赞成者杰克·施瓦格(Jack Schwager)常称之为盈利因子或盈利能力因子的盈利与损失比率。它表明,当分子中的累积利润超过损失时,该比率大于 1,反之亦然。这是算术盈利预期的另一种版本,作为比率而不是增量。

def rolling_profits(returns,window):
    profit_roll = returns.copy()
    profit_roll[profit_roll < 0] = 0
    profit_roll_sum = profit_roll.rolling(window).sum().fillna(method='ffill')
    return profit_roll_sum

def rolling_losses(returns,window):
    loss_roll = returns.copy()
    loss_roll[loss_roll > 0] = 0
    loss_roll_sum = loss_roll.rolling(window).sum().fillna(method='ffill')
    return loss_roll_sum

def expanding_profits(returns): 
    profit_roll = returns.copy() 
    profit_roll[profit_roll < 0] = 0 
    profit_roll_sum = profit_roll.expanding().sum().fillna(method='ffill') 
    return profit_roll_sum 

def expanding_losses(returns): 
    loss_roll = returns.copy() 
    loss_roll[loss_roll > 0] = 0 
    loss_roll_sum =    loss_roll.expanding().sum().fillna(method='ffill') 
    return loss_roll_sum 

def profit_ratio(profits, losses):    
    pr = profits.fillna(method='ffill') / abs(losses.fillna(method='ffill'))
    return pr

window = 252
df['pr_roll'] = profit_ratio(profits= rolling_profits(returns = tt_log_returns,window = window), 
                             losses= rolling_losses(returns = tt_log_returns,window = window))
df['pr'] = profit_ratio(profits= expanding_profits(returns= tt_log_returns), 
                             losses= expanding_losses(returns = tt_log_returns))

df[window:] [['tt_cumul','pr_roll','pr'] ].plot(figsize = (20,8),secondary_y= ['tt_cumul'],
                            style = ['b','m-.','m'], 
  title = str(ticker)+' cumulative returns, Profit Ratio, cumulative &  rolling '+str(window)+' days') 

上述代码计算了滚动和累积盈利与损失比率。结构是对称的,所以让我们集中精力在滚动利润上。

  1. 通过复制收益序列来实例化一个profit_roll数据框架。将损失分配为0。这将保留数据框架的形状。

  2. 使用rolling方法计算滚动总和。使用fillna方法填充#N/A缺失值。

  3. rolling_profitsrolling_losses函数中计算profit_ratio

  4. rolling 函数后跟着累积版本。expanding() 方法在合成上与流行的 cumsum() 方法相同。唯一的区别是,当遇到缺失值时,expanding() 不会重置为 0,而 cumsum() 会重置为 0

图 6.6:Softbank 累积回报和利润比率:滚动和累积

上图将滚动和累积利润比率与信号并列绘制在一起。随着信号的波动,利润比率急剧下降。相反,在趋势性市场中,利润比率上升。

追随趋势的策略表现出令人印象深刻但波动较大的绩效。它们经历了长时间的低迷表现,这对管理者和投资者的情绪资本产生了影响。它们的主要挑战是保持累积损失的小额化。利润只有在损失保持较小的情况下才会显得巨大。

为了说明这一现象,最初的海龟交易员之一曾经说过,以 30% 以上的胜率,他们承担了预期失败的仓位。这种微妙的心态转变使他们对风险管理更加警惕。

均值回归

均值回归 策略可以将大量小额利润累积起来。它们依赖于极端情况最终回归*均值的前提。它们套利市场的非效率。均值回归策略实质上捕捉了市场非效率修正所需的时间。例如,一份认股权证的价格可能相对于其基础股票来说便宜。随着时间的推移,价格将会趋同,并且差距将会缩小。它们通常具有低波动性、持续稳定的绩效。它们在建立的市场中表现良好:牛市、熊市或横盘市。均值回归策略的偏好市场通常是价格以半可预测方式振荡的横盘阶段。它们可能会发现牛市或熊市阶段更具挑战性,但有大量的经验数据显示有才华的管理者在这些市场中表现出色。同样,风险管理是专业人士和外行之间的分水岭。

均值回归策略在制度变化期间表现不佳。例如,在牛市中,做多高 beta、做空低 beta 将取得很好的效果,但随着制度过渡到横盘和熊市,这些策略将大幅失去收益。上一次牛市的宠儿有时会在随后的熊市中率先下跌。它们在尾部事件中也表现不佳。做空伽马基金多年来表现良好,直到在 2008 年全球金融危机期间的三周内惨遭失败。

图 6.7:经典的多空均值回归 P&L 分布

均值回归策略的特点包括:

  • Alpha 生成:均值回归策略具有较高的周转率。它们可以迅速积累小额利润。

  • 负偏斜:左偏 P&L 分布。不利的尾部比率:亏损大于盈利。上述图表是时间荣耀的格言“拿利润你不会破产”(you can't go broke taking profits)的视觉表现。事实证明,如果亏损太大,你可能会破产。均值回归策略利用效率低下进行套利。当效率低下得到纠正时,交易被关闭。有时,这些效率低下会持续存在。由于最初的前提是效率低下无论如何都会得到纠正,所以不会执行止损。这导致了罕见但毁灭性的打击。

  • 高胜率:通常超过 50%。市场并非始终在所有时间段都是高效的。

  • 中高周转率:实际上,效率低下的情况比有效市场假说EMH)和随后的学术理论通常建议的更频繁出现。

  • 稳定低波动小利润:均值回归策略在稳定市场环境中利用多个小的效率低下进行套利。

  • 潜在毁灭性的左尾损失:均值回归策略在效率得到纠正的成熟市场中表现良好。在制度变革时,过去的效率低下仍然存在时,它们失败了。有趣的是,随着均值回归策略的衰退,趋势跟随策略开始表现良好。

  • 缓慢的复苏:均值回归策略积累小利润但产生大损失。需要很多小的胜利来抵消少数大的损失。

正如我们之前看到的,均值回归策略持续产生一致的小利润,但遭受罕见但游戏终结性的挫折。均值回归策略的风险在于尾部。几次毁灭性的损失有能力击沉船只。毕竟,泰坦尼克号的船长有 99% 的胜率。因此,最相关的风险度量是最大利润与最糟糕损失的比率,或尾部比率:

def rolling_tail_ratio(cumul_returns, window, percentile,limit):
    left_tail = np.abs(cumul_returns.rolling(window).quantile(percentile))
    right_tail = cumul_returns.rolling(window).quantile(1-percentile)
    np.seterr(all='ignore')
    tail = np.maximum(np.minimum(right_tail / left_tail,limit),-limit)
    return tail

def expanding_tail_ratio(cumul_returns, percentile,limit):
    left_tail = np.abs(cumul_returns.expanding().quantile(percentile))
    right_tail = cumul_returns.expanding().quantile(1 - percentile)
    np.seterr(all='ignore')
    tail = np.maximum(np.minimum(right_tail / left_tail,limit),-limit)
    return tail

df['tr_roll'] = rolling_tail_ratio(cumul_returns= df['tt_cumul'], 
                             window= window, percentile= 0.05,limit=5)
df['tr'] = expanding_tail_ratio(cumul_returns= df['tt_cumul'], percentile= 0.05,limit=5)

df[window:] [['tt_cumul','tr_roll','tr'] ].plot(secondary_y= ['tt_cumul'],style = ['b','g-.','g'], figsize = (20,8),
    title= str(ticker)+' cumulative returns, Tail Ratios: cumulative &  rolling '+str(window)+ ' days') 

代码包括以下步骤:

  1. cumul_returns:在此函数中,returns是指对数收益np.log(px/px.shift())。使用cumsum()方法计算累积收益并填充缺失值。

  2. 使用quantile方法计算滚动左尾和右尾。

  3. 此系列有点跳跃——分母为 0 会返回错误,因此将错误设置为ignore

  4. 设置上下限以避免两侧的无限数。

所得到的图表显示了累积收益和滚动和累积尾部比率。

图 6.8:Softbank、累积收益和尾部比率:滚动和累积

正如您所看到的,我们计算了累积和滚动基础上的 5%尾部比率。正如您所看到的,尾部比率很快就会偏向无穷大或零。这就是为什么应该通过极限将其限制在范围内。请注意,尾部比率不像我们之前看到的利润比率那样反应迅速。该比率不适用于趋势跟踪策略。它的一致性非常高,以至于极限必须降低到第 5 和第 95 百分位才能看到。这说明了这些策略确实具有不同的风险特征。

总结

让我们回顾一下。那神秘的、神秘的、神话般的、神奇的交易优势不过是我们在学校学到的一个叫做收益期望的小公式。现在,事实证明,具有正向交易优势的策略往往分为两大类。这种情况不论时间跨度、资产类别、工具和市场阶段如何。市场参与者期待非效率性要么纠正并恢复到*均水*,要么持续并形成趋势。这些策略是互斥的。它们具有相反的回报和风险特征。

然后,我们花时间了解了每种策略类型的特性,以便我们能够想出更好的方法来设计一个更优越的交易优势。现在我们了解了这些策略的行为方式,下一步是卷起袖子,打开引擎盖,调整信号引擎。

第七章:提高您的交易优势

“我从不在最低点买入,我总是卖得太早。”

– 纳撒尼尔·德·罗斯柴尔德男爵

穿过的两人中,优赛恩·伯特和罗杰·班尼斯特都跑得很快。前者是短跑运动员。后者曾跑过一英里。同一项运动,不同的学科。这里的等价性在于你有一个主导风格:要么是均值回归,要么是趋势跟随。磨练你的交易优势的最佳方式是改进你的主导风格。第一步是从最佳策略会是什么开始,然后逐渐将你的风格朝着那个方向推进。

建立一个统计上健壮的交易优势是关于夺回控制权。你无法控制市场未来一周或一年的走向,但你完全可以控制今天你的投资组合中发生的事情。以下章节是邀请你以不同的方式思考你的主导风格以及你如何构建更好版本的交易优势。

到目前为止,我们知道交易优势有两个模块:信号和资金管理。我们也清楚地看到了趋势跟随或均值回归积极交易优势的视觉表现。接下来,我们将将利润和损失P&L)分布分成两部分。首先,我们将介绍您可以采取的所有控制损失的步骤。然后,我们将看看您可以采取的增加利润的步骤。最后,我们将介绍一种创新的投注大小策略。

在此过程中,我们将涵盖以下主题:

  • 混合交易风格

  • 止损的心理学

  • 止损的科学

  • 提高您的交易优势的技巧

  • 如何倾斜您的交易优势,如果您的主导风格是均值回归

您可以通过以下链接访问本章节中所有图片的彩色版本:

混合交易风格

正如我们在第六章中发现的,交易优势是一个数字,这就是公式,均值回归策略具有负偏度。几次巨大的损失将使船沉没。趋势跟随策略具有正偏度。几个王子将弥补所有的青蛙。这两种策略都有好坏属性,可以总结在以下表格中:

均值回归 趋势跟随 混合
获胜率
波动率
左尾 长的 短的 短的
右偏 短的 长的 长的
偏度 负的 正的 正的

一个理想的策略将结合两种风格的积极属性,并尽量减少两种风格的缺点。它将是一个具有高胜率、低波动率和短左尾和长右尾的混合体。混合的损益分布会是这样的:

图 7.1:混合的损益分布具有高胜率和右偏

均值回归市场参与者和趋势跟随者来自不同的信念体系。前者相信效率最终会回归到*均水*,而后者则期待它们会持续存在。虽然这些信念体系是不可调和的,但仍然有可能将你的主导风格与相反体系的一些属性融合起来。

下面部分概述的技术将可持续地改善表现。然而,我们都知道,顶尖运动员与其他人的区别不在于外在的身体游戏。而是在于他们内在对话的质量,他们的内在游戏。如果我们不承认房间里的大象,那么这些技术都不会起作用。

将职业卖空者与游客区分开的是设定止损的能力,更重要的是恪守止损的坚韧。

止损的心理学

"希望是一个错误。"

– 疯狂马克斯,后末日澳大利亚哲学家

单单在美国,减肥行业就价值 640 亿美元。然而,从 1999 年到 2016 年,肥胖率增加了 30%。减肥行业在商业上获得了成功,但在实践中却失败了,仅仅因为它试图解决了错误的问题。这对我们有很多关于止损心理学的教训。

我们集体肥胖的原因并不是我们摄入的食物。而是我们如何与食物相处。如果你的父母告诉你,“吃你的汉堡,它会让你变强壮”,而不是“吃那些含有致癌基因的转基因蛋白质,注入了抗生素,它们会让你心血管健康问题的风险增加三倍”,那么你可能会不那么愿意参与圣牛肉的食用。

下面的《科学美国人》报告讨论了喂食抗生素的牲畜所带来的健康风险:www.scientificamerican.com/article/most-us-antibiotics-fed-t/

市场上每个人都知道赚钱的秘诀:"减少损失,坐享收益。" 减少损失并不是什么高深莫测的学问。这种数学在初中和高中之间。然而,是我们对损失的态度使得遵守止损成为难以逾越的障碍。要求正确常常凌驾于赚钱的必要性之上。

当人们说,“我不相信止损”,他们真正的意思是,“我不愿承认我错了。” 他们往往非常清楚出了什么问题。然而,他们的自尊心愿意忍受更多的痛苦,希望情况会好转,他们最终会被证明是正确的。傲慢总是优先于利润。诺贝尔奖得主丹尼尔·卡尼曼和阿莫斯·特韦斯基称我们对损失的风险寻求态度和对利润的风险规避态度为固定效应。

如果盈利等同于正确,那么从逻辑上讲,亏钱就意味着错误。因此,任何损失都直接攻击我们的自我形象。自我感觉需要是对的,但不觉得自己有义务赚钱,并且将会默认采取防御机制——否认和转移——以保护自己。这驱使我们牺牲利润,忍受长时间的剧痛,危及我们的工作、声誉,甚至我们的家庭。在自我投降之前,声誉、公司和国家都曾倒台。

底线是,过度受过教育、极度竞争和极度复杂的 40 岁对冲基金经理们仍然在潜意识中操作着一个 5 岁孩子的操作系统。他们只是更擅长制定复杂的合理化。

比尔·阿克曼和凯利安(VRX)的公开丑闻说明了自我形象优于利润的首要地位。当 VRX 从高峰下跌了 50% 时,另一种选择很简单:坚持流程或坚持股票。对其他人的钱的谨慎管理(OPM)决定关闭部分或全部头寸,因为股价必须上涨 100% 才能恢复到之前的水*。另一种选择是假设分析是正确的,但是“市场是错误的”,并且挑战市场。阿克曼先生爱国地选择了通过以 104 美元购买另外 200 万股来焚化另一批 OPM。需要正确的需求超过了对其投资者谨慎管理风险的受托责任。

随后,凯利安又一次下跌,从高峰下跌了总计 92%。在这一点上,价格必须上涨 11 倍才能打*。该头寸以每股约 11 美元清算。有时我们获胜,有时我们学习。在 2016 年致股东的信中,阿克曼先生重申了谦卑的重要性:“要成为一名优秀的投资者,首先需要有信心,在其他人对你正在追求的机会高度怀疑的时候,投资,即使没有完美的信息。然而,这种信心必须通过谦卑来谨慎*衡,以认识到自己错了。”

这使我们想到了我们赢家的命运。康宁曼和特沃斯基已经证明,当涉及利润时,我们是风险规避的。事实上,我们并不是天生渴望早早获利的。 初学者的幸运 是对低概率事件采取大风险的另一种说法,这是任何经验丰富的玩家都不敢轻举妄动的事情。我们并不是天生的风险规避者。婴儿经常摔倒。他们重新站起来,继续前进。

我们只有在经历了几次创伤性的损失之后才会变得风险规避。一旦我们经历了损失的痛苦,我们就会在我们眼前的利润开始蒸发时急于保护剩下的任何利润。如果我们从未经历过损失,我们就不会觉得有必要对利润采取风险规避措施。如果不是因为通过损失学到的痛苦教训,我们会很愿意接受风险最大的策略。底线:跑赢家然后割败者是我们的本性。

如果我们想在这场与自然的斗争中取得成功,我们需要重塑与损失的关联。只要我们保持一个以结果为导向的观点,那么自然,即我们的杏仁核,将战胜理性,即我们的前额叶皮质。

在执行交易员的英语中,只要我们认为赚钱等于做对了,而亏钱是给失败者的,我们就会找借口不去承担那些损失。我们需要将做正确的事与结果无关地正确联系起来。

这里有一个六步过程,完全改变你对止损的看法。

步骤 1:问责制

“生意是一种拖延。”

– 蒂姆·费里斯

自我保护是自我的职责,不惜一切代价,无论何时。也许你现在已经得出结论,认为你对毒性自我的影响是免疫的,但却在其他市场参与者中见证了它。嗯,如果这些想法刚刚闯入你的脑海,那么你的自我刚刚在耍花招。根据丹尼尔·戈尔曼的说法,自欺是一种根深蒂固的内置机制,它掩盖了自己的踪迹。以下是两个例子,将帮助你自己看清你的潜意识有多善于欺骗你。

例子 1:上次你的投资组合出现大亏损时你做了什么?你读了每一份分析师报告吗?你拜访了公司或分析师吗?你更新了你的盈利模型吗?你了解了股票的情况,一个代指是否受欢迎的做空的术语?你在论坛上与同行抱怨了吗?你喝醉了,责怪别人,或者拿家人出气了吗?还是,你只是设置了止损然后继续前进?

最*关于学术拖延的研究表明,在考试之前,学生们参与了一些对大脑产生积极影响的重要活动,比如整理房间、整理桌子或给父母打电话,但没有参与像学习考试这样的必要活动。他们实践了一种心理会计:通过做好事,他们希望能弥补未做必要事情的遗憾。市场参与者也是如此。当头寸变得不利时,我们参与一些对大脑产生积极影响的任务:更新盈利模型或与分析师、专家和公司联系,但拖延不可避免的事情:割损。

示例 2:让我们用绩效的影响来看得更*一点。在我以前的一份工作中,我很幸运地能够访问几位经理的所有交易。我开始分析它们,希望从这些杰出头脑中得到一些经验教训。最大的发现是一个反直觉的游戏规则改变者。如果在每个组合中排除了三个表现最差的股票,每个经理在整个样本期内每年都将超过基准(在成本之前)。然而,如果排除了表现最好的三只股票,则不是每个人都会表现优异。此外,超额收益不会保持一致。

每一个市场参与者都曾延迟关闭一个亏损的持仓,期望价格回来再稍微涨一点就可以以更有利的报价退出。不幸的是,一天变成了一周,一个月,依此类推。坏损失不是一夜之间发生的。它们会腐烂并且溃烂。第一步是保持一个整洁的交易日志。始终牢记你的*均损失和最大损失。下次有人问起你的交易优势时,你的默认回答应该是这样的:“哪边:多头、空头还是持*?”这将避免由于你自己的自我抵抗而导致对市场事件的迟钝反应。

步骤 2:重塑你对损失的联想

让我们重新审视一下减肥问题。健康的饮食选择就像是卖方维护研究:索然无味且乏味。我们知道坚持节食会使我们身材更加匀称。所以,我们继续努力,减掉那些多余的赘肉。但是一旦达到减肥目标后会发生什么?绝大多数人会复发。有些人会从一种饮食转换到另一种,希望总有一天会有所突破。我们失败了,因为我们只关注了节食的身体方面:减肥。我们虽然在节食期间按部就班地做了一切,但我们忘记了教训。我们在节食期间正确地吃了适量的合适食物,但我们仍然保持着会最终导致我们重新养成不良饮食习惯的不健康联想。食物不是问题所在。通常,减肥不是身体问题,而是心理问题。

对于止损也是一样。我们在理智上理解它们的重要性。当我们经历困难时,我们会毅然割掉输家。但是接着来的是这种立场:“如果我们再给它一个机会,最多再多一个星期,它就会好转。这只是暂时的。”我们内心的白痴与我们的精神病性的另一自我——经济人——进行着谈判。最终的结论是这个例外:“就这一次,我们可以放弃止损。”接着我们知道的是,投资组合看起来就像是一片烂苹果园。只要我们将正确与在每一笔交易上盈利联系在一起,我们就是从结果导向的角度出发行事。

我们无法抵挡我们追求正确的需求,但我们可以改变我们选择追求正确的事物。与其追求金钱,我们可以将正确与坚持遵循投资过程的纪律相联系。我们从一个我们实际上无法控制的结果转变为以过程为导向的视角。

这样做有两个好处:

  • 成功变得可以量化和可测量。一次交易是随机的。一百次交易是一个数据样本。试图控制个别结果是徒劳的。但完全有可能衡量对投资过程的遵循程度。好消息是,在历史上的每个文化中,尤其是在我们行业中,纪律都是一种美德。

  • 欺骗的诱惑自然会消失。正确不再关乎离散系列的结果。你可以一次又一次地输钱,但仍然是对的。当你始终从这个角度出发行动时,你会在神经通路中重写,从而重塑你的身份。

一个更先进的版本是将这种过程性思维变成游戏化。这里有一个小故事。2012 年底,首相安倍晋三决定振兴日本经济。市场环境立即从沉闷的熊市变为狂热的牛市。每次一只股票触及止损点,我就会在 YouTube 上播放詹姆斯·布朗的I Feel Good的前奏,并做一些《早安,越南》中罗宾·威廉斯的模仿。有一次,一位同事走到我跟前说:“你真的喜欢詹姆斯·布朗,是吗?”我的回答是:“嗯,我今天刚刚止损了。”

这个轶事可能有些傻,但其中确实有一点科学性。大脑讨厌接受止损。它也渴望即时满足。那个小小的铃声带来了多巴胺的冲击。随着时间的推移,它压倒了对遵守止损的不情愿,并重新塑造了与损失的关联。到了第 30 次连续止损时,我已经免疫了,可以毫不费力地接受接下来的一百次。尝试并自己看看。从小处开始。在执行止损后立即奖励自己。经过几轮后,你可能会注意到你的大脑已经开始渴望止损。你大脑中的原始部分会为了它的多巴胺冲击而做任何事情。你的任务是找出将奖励附加到什么上面。

纪律的资金管理应该像牙齿保健一样无聊。人们很少会对使用牙线感到兴奋。然而,大脑渴望兴奋和新奇。因此,如果没有乐趣,要建立起持久的习惯就很困难。建立良好基金管理习惯的一种方法是引入奖励。以下是实践中如何做到的:

  1. 每周或每月评估你对系统的遵循程度。

  2. 决定一个让你感觉良好的奖励。可以是任何东西。例如,我的第一个对冲基金的负责人会买一瓶葡萄酒,其价格与累积表现相关。每个人都期待着那个星期五的释放压力。

  3. 每次打破你的最高分,立即奖励自己。

游戏化轻松地完成两件事。它使我们参与有利可图的活动,并驱使我们打破自己的最高分。

第三步:何时设置止损

婚姻合同之所以被称为婚前协议而不是婚后协议,是有原因的。当我们进入一个头寸时,情绪就会涌现出来。我们不再是旁观者。我们在比赛中,而我们内心的白痴在驾驶座上。设置止损的最佳时间是在进入交易前五分钟。其次,风险预算决定头寸大小。止损是方程中的一个变量。如果你不限制自己可以承受的损失,你很可能会损失比你应该损失的更多。

止损不是一个故事。一些自由裁量市场参与者声称,当故事改变时,他们会改变自己的观点。问题在于,我们不是公正的裁判。我们始终努力使我们的行动与我们的信念一致。当我们的行动不再与我们的思想匹配时,不适感就会产生。这被称为认知失调。我们只剩下一个简单的选择:调整我们的行动与我们的信念一致,或者改变我们的观点以适应新的事实。虽然前者是逻辑的选择,但我们遗憾地经常选择后者。当价格对我们不利时,更容易的选择是改变我们告诉自己的故事。到故事改变的时候,我们最初的论点早已走上了错误的发展道路。这种现象的一个简单表现是我们对亏损头寸的态度。我们知道大约一半的交易会失败,但情感上我们却表现得好像我们必须始终 100%正确一样。在执行交易员的英语中,这被称为傲慢。

对于自由裁量市场参与者的一个有效的引导是在交易开始时为每笔交易分配一个预算。超出该预算后,承诺将头寸减半。如果交易随后成功,利润将补偿已实现的损失。如果它继续恶化,处理一个小头寸比处理一个高风险头寸更容易。止损是一个预算管理的练习。因此,它是一个价格。承诺将其与入场成本和价格一起写下来。不要相信你的大脑来记分。你内心的白痴会重新协商并欺骗你犯下愚蠢的错误。

第四步:预先尸体检查:对过度自信的疫苗

后事分析是金融服务业的一个热门话题。在金融业中,它通常指的是管理层用事后完美的远见通过你的过去交易的官僚化过程。如果这本书有两个主要观点,那么预后事分析应该是其中之一。预后事分析是过度自信的最终解药。预后事分析是由心理学家加里·克莱因发明的一种技术,它涉及向前移动时间,并将你即将做出的决定想象成以失败告终。

乐观主义通常在进入前达到顶峰。没有人在自豪地走向祭坛时会想到离婚。当我们下订单时,我们内心的白痴会唱一些有毒的合理化歌曲,比如:“当然它会是一笔赢家,否则,我为什么要做那笔交易呢?我是那么愚蠢吗?”不幸的是,冷酷的统计现实证实了我们的确是那么愚蠢的。即使我们的长期胜率低于 50%,我们也会像每笔交易都会是赢家一样预测行动。

对每一笔交易都要进行这个练习:在下订单之前,想象它将是一笔必须止损的失败者。想象自己在亏损时关闭交易。感受到你的情感资本流失。用你所有的感官使这个想象尽可能生动:嘴里有一股苦味,视野狭窄,手心出汗,无助,内心对话致命。那么,你会怎么做呢?调整你的仓位大小并发送订单。这种技术可能看起来是自虐的,但它完成了两件事:

  • 它确保保守的仓位控制:如果你进入一笔交易时预计会失败,你将会下更小的注。你也会远离流动性不佳的股票选择。你将成为更好的风险管理者。

  • 它让我们预先处理我们的悲伤。我们通常期望交易成功。当它们失败时,我们会以清算的方式来悲伤。遵循伊丽莎白·库伯·罗斯的经典五个悲伤阶段,我们花费时间、精力和金钱与不可避免的东西讨价还价。如果你做一笔交易时期望它成功而它却没有,这会加强学习的无助感。如果你期望每一笔交易都会失败,那些成功的交易将是愉快的惊喜。那些失败的交易将如期执行。因此,预后事分析消除了情绪的负担。提前包装你的悲伤使你对损失更加精确。

就像快乐生活的秘诀是将死亡视为每天的伴侣一样,市场赚钱的悖论是接受损失并继续前行。

第五步:执行止损:原谅我们的错误

“痛苦是必然的,受苦是可选的。”

– 兰德·豪威尔

止损就像任何其他交易一样。然而,我们赋予它的意义可能是毁灭性的。每当你因为止损而责备自己时,你都在剥夺自己的教训。

最*关于自我原谅的研究表明,那些被教授了自我原谅技巧的学生提高了他们的学习能力,并随着时间的推移表现得更好。当他们越过自己的界限时,原谅自己的人往往会从自己的错误中学习。而那些不原谅自己的人则否认了从错误中学习的好处。悖论在于,通过惩罚我们的过失,我们将自己置于重复错误的命运中。相反,要对自己好一点。像对待你的孩子一样安慰自己。

这就是它的帮助之处:

  • 你原谅自己越多,执行止损就会变得越不可怕。

  • 执行止损越容易,开新头寸就越容易。

  • 执行越顺利,表现越好。

底线:原谅你的错误,你将成为更好的投资组合经理,并更擅长忍受市场的艰辛。

第六步:蔡格尼克效应对我们执行止损的启示

布鲁玛·蔡格尼克是 20 世纪初在维也纳生活的一位心理学家。当她正在享受咖啡时,她注意到一名服务员可以以惊人的准确度记住所有顾客的订单。在回家的路上,她意识到自己忘记了围巾,于是回到了那个地方。然而,尽管这名服务员可以轻松地记住所有未完成的订单,但他却不记得半个小时前见过她。这让她对我们的大脑如何处理未完成的任务有了重大发现。未完成的事情(在这种情况下,是一个未完成的订单)往往在我们的脑海中挥之不去,而已完成的任务(已支付并离开的顾客)很快就被遗忘了。

在任何时候,我们的投资组合都会有问题儿童。它们总是占据着比它们应得的更多的心理空间。它们总是挥之不去,直到我们最终鼓起勇气将它们踢出去。现在,你有没有注意到一两个星期后,你几乎不能记住那些让你如此困扰的职位的名字?这就是被应用于投资组合管理的蔡格尼克效应:眼不见,心不烦。迅速处理问题儿童能够实现两件事情:保护你的财务资本免受进一步侵蚀。更重要的是,它释放了心理空间,并保护你的情感资本免于螺旋式的自我责备。

蔡格尼克效应是执行止损的强大动力。你最不希望的就是让小损失恶化成全面的大失误。执行止损从来都不是一个容易的决定。如果你回顾一路上的所有损失,你可以安全地得出结论:没有发生灾难性的事情。事实上,你还在那里,部分是因为你做出了那些艰难的决定。所以,下次你犹豫不决时,告诉自己,现在可能看起来很困难,但你会克服它,并在下周感到清爽。

现在我们已经提升了内在游戏,让我们努力提高外在游戏,并使那些统计数据看起来不错!

止损科学

“利润只有在损失保持得足够小的情况下才显得可观。”

– 迈克尔·马丁

大多数市场参与者都对损失对底线的伤害有一些模糊的概念。他们从未真正将损失的影响形象化。损失对你起着几何级数的负面作用。50%的回撤意味着你需要实现 100%的利润才能回到盈亏*衡点。举例来说:有人以 100 的价格买入一支股票。你另一边接手交易并将其降至 50。游客一直持有,因为长期故事仍然完整。那个固执的业余者将不得不达到 100%的利润才能回到盈亏*衡点。

下面这张看似无害的图表展示了一个足以说服任何理性市场参与者的强大信息,那就是保持损失小是唯一的选择。下方线条表示从峰值到-90%的回撤。上方线条表示恢复这些回撤所需的百分比增长。在-10%的回撤情况下,账户必须增长 11.2%才能回到原点。在-20%时,需要增长 25%才能弥补损失。在-90%时,需要 10 倍的增长才能弥补损失。因此,我们接下来将看到的大多数技巧都与损失有关,这些损失会几何级地减少账户余额。下次你想要抱住一个失败者不放时,拉起这张图表提醒自己:为了证明自己是对的而付出的代价就是破产:

图表

图 7.2:回撤水*和恢复损失所需的百分比增益

能够设定和遵守止损是专业空头卖方和游客之间的区别所在。学会如何设置止损以最小化回旋和最大化风险-回报需要实践。需要谦卑和勇气在止损被触发后仍然继续下一笔交易。

止损是交易边缘公式中最重要的变量。它直接影响三个变量:获胜率%、亏损率%和*均亏损%。相比之下,入场直接影响这些变量中的任何一个。止损还在赌注大小和交易频率方面起着至关重要的作用:止损越紧,下注越大,但交易频率也越高。

市场参与者有时对止损持怀疑态度。然而,止损就像寿司刀一样。如果你不知道如何使用它们,你会割伤自己。在正常情况下,没有人会因自己的不慎而责怪一把寿司刀。同样地,只有那些没有做好功课的游客才会用止损割伤自己。以下是三个简单的原则。

止损是一个逻辑的信号干扰问题

止损被广泛误解。它们不是日常交易决策的一部分。等待止损被触发是一种高度低效的退出头寸的方式。你不希望你的安全气囊在每个红灯处都爆炸。理想情况下,你希望在止损被触发之前减少、退出或者甚至反向头寸。

把止损看作信号,把波动性看作噪音。如果你把信号放在噪音带内,你所得到的只会是噪音。市场是喧闹的。通常在主要变动之前会有几次虚假启动。如果你把止损放在波动性带内,你可能会在几次振荡后才做出正确的决定。这将迅速侵蚀你的资本基础。你需要大幅度的变动来弥补之前的小损失。

你希望把止损设置在一个明确的信号点上,表明你的假设被否定了,或者在另一方面可能有有效的进入点。这可以通过波动性测量,如*均真实范围ATR)或标准偏差来完成。这些信号也可以是逻辑转折,如略高于或略低于高/低点的几个买入/卖出点。

止损是一个统计问题

新手交易者喜欢保护他们的利润,因此他们设置紧密的止损。止损越紧,距离止损的距离就越小,因此对于相同的风险预算来说可以承担更大的仓位。这导致了较大的*均仓位大小和较低的*均亏损,但是高的败率。紧密的止损往往很容易触发。这也会增加交易频率。失败来自于小损失的积累。例如,如果需要三次尝试才能做对,那么价格必须移动三倍的距离才能维持正的盈利期望值GE)。

老手交易者享受到了一个良好睡眠的特权。他们已经了解到市场需要活动空间。他们将止损设置得更宽松一些。这导致了较小的*均仓位大小,较大的*均亏损,更高的胜率,较低的败率和较低的交易频率。下表总结了止损对 GE 的影响:

紧密 宽松
胜率 较低 较高
亏损率 较高 较低
交易频率 较高 较低
仓位大小 较大 较小

在 GE 方程中,止损是迄今为止最重要的变量。了解如何设置止损将对任何策略产生巨大影响。相比之下,选股(即进入市场)只对胜率和败率产生间接影响。

故事的寓意是:给市场足够的活动空间,但不要给它太多的逃跑空间。可能存在一个数学上的最优解,但市场条件随时间而变化。波动性并不均匀。

止损是一个预算问题

止损用于计算仓位大小。距离入场成本越远,仓位越小,反之亦然。这将对绩效、波动性和股票选择产生影响。

宽止损将导致小仓位。这些将产生较低的绩效和较低的波动性。波动性较高的股票往往具有较宽的止损,这导致了小仓位。当是时候根据仓位大小对信号进行排名以分配资本时,低波动性股票将被系统地优先考虑。

当从长位置转换到短位置时,可以预期市场会有一些阻力。将止损设置在一个能够使你的论点无效的水*上,相当于采取了一个小的试探性立场。如果事情没有按计划进行,损失将是最小的。如果成功,这个小立场将为后续的行动提供资金支持。

提高交易优势的技巧

接下来,我们将介绍提高交易优势的技巧,这是本章的主要焦点。我们将从考虑如何缩短左尾并将损失峰值接*盈亏*衡开始。

技巧 1:两段论游戏:如何削减失败者、抓住赢家,并在提高交易优势的同时保持信念

在世界上每个医院都有一个不成文的规定:外科医生不应该给自己的家人做手术。当涉及到自己的孩子时,就不存在专业的超然态度。然而,在投资领域,基本的离散市场参与者对止损的概念感到困惑。

他们不断被要求捍卫他们的信念,但期望对他们的损失进行外科手术般的处理。他们被迫失去中立性,但仍需要保持专业的超然态度。如果他们想掌握做空游戏,离散的参与者将不得不克服他们的不情愿。

这个强大的技巧将帮助你实现不可能的事情:削减失败者、运行赢家、保持信念,同时机械地提高交易优势。它专门为在止损概念上苦苦挣扎的离散市场参与者设计。

处理今天的失败者比预测明天的赢家容易得多。只要将失败者保持在赢家总和以下,通用电气就保持为正面。如果你将那些失去一半*均贡献的失败者减半,机械地说,你就赢了。在实践中,这就是做法:

  1. 将所有仓位分为贡献者和负面因素。

  2. 计算总体*均贡献或*均利润。市场参与者如果具有异常长的右尾,可能希望使用中位数而不是均值。

  3. 一旦失去了*均贡献的一半,将所有负面因素的权重减半。

对于剩余的持仓,只有两种情况会发生:

  1. 股票扭转并开始贡献。这将抵消损失。加入新的交易。

  2. 仓位继续受到伤害。它们只会减半地减少并减半地加速。更重要的是,对于小仓位比大仓位更容易保持临床分离。

“两个部分的游戏”为基本投资中最古老的问题提供了一个简单而优雅的解决方案。坚持和顽固之间有着微妙的界限。投资者希望经理有信念。然而,他们不原谅固执。海上的英勇不在他们的家谱中。他们不想和船一起沉没。 “两个部分的游戏”调和了对信念的需求和如果一个头寸开始造成伤害则需要采取行动的需求。你通过保留一部分头寸展示了信念,同时通过减少风险展示了谦卑。

其次,这种方法遵循绩效循环。当你的风格有效时,你的*均利润增加。你可以承担更多风险,增加头寸并容忍更大的损失。当你的风格不受欢迎时,*均利润缩小,从而允许更小的损失,即更小的头寸。

第三,交易优势机械性地得到改善:损失相对于利润更小。这种方法将损失分布倾斜到右侧。它将损失交易的模式,即赔钱交易的高峰,推向了接**衡点。在执行交易员的英语中,当利润减少时,要更快地缩小损失。最后,它改变了“正确”的定义。这不再是对每个单独想法的盈利的二元结果。正确就是遵守一个将导致更高总体盈利的过程。简而言之,它不再触发战斗、逃跑或冻结本能,而是激活思考大脑。通过这种方式,这个“两个部分的游戏”减少了压力并提高了盈利能力。

技巧 2:通过移动止损减少损失

“你应该始终有一个最糟糕的点。唯一的选择应该是更快地出局。”

– 理查德·丹尼斯,海龟养殖者

进入后,头寸最脆弱。盈利交易需要时间成熟。与此同时,不盈利的交易通常很快崩溃。这种时间差导致账户余额的侵蚀。你可能无法减少假阳性的数量,但仍然可以通过在达到止损之前插入损失缓解退出来限制损失。这就是移动止损的地方派上用场。移动止损是随着价格移动的移动止损。它有两个目标:

  1. 当价格有利地移动时,减少风险。

  2. 当价格开始朝着另一个方向移动时,尽量少地返还利润。

跟踪止损不是万灵药。它们对于保护利润是有效的,但对于捕捉长期趋势是适得其反的。这在空头方面尤其如此。跟踪止损可能会在市场恢复其下行趋势之前过早地使你退出头寸。跟踪止损应该被审慎使用,以在交易最脆弱时迅速降低风险。这里的目标是利用每一次有利的价格波动来降低风险。这可能会对胜率产生不利影响,但会导致较低的*均损失和较小的累计损失。这将使损失模式更接*于持*。

让我们用一个数值例子来说明逻辑止损对头寸规模、损失缓解、交易优势和整体权益曲线的影响。假设市场在 100 处再次打印本地高点,低于 108 的历史高点。这看起来像一个顶部。当前价格水*约为 98。你决定进入空头头寸。

让我们起草一个标准的战斗计划:

  1. 在顶部设置固定止损:如果市场触及历史高点,那显然是看涨的。

  2. 设置跟踪止损:作为一名经验丰富的交易员,你预计 100 的高点会再次被测试,因此你将跟踪止损初始化为 101,略高于本地高点。

  3. 选择止损来计算你的头寸规模:你可以选择固定止损和跟踪止损来计算你的头寸规模。

  4. 计算你的头寸规模:你当前的头寸规模算法给出了一个 10 万美元的风险预算,除以到止损的距离得到一定数量的股票。我们将在下一章详细考虑头寸规模。

  5. 设置风险降低的目标价格:你在打印后检测到了本地高点,考虑到滑点和交易成本,你的*均价格为 98。你设置了目标价格为 95,在该价格退出 3/4 的头寸(以维持正面期望),并让剩余的头寸免于风险。如果市场出现强劲反弹,你仍有时间进行*仓。

现在,让我们选择哪种止损来锚定你的头寸规模。情况 1、2 和 3 依赖于相同的信号。情况 1 假设信号有效,并将持有头寸直到被证明错误。情况 2 使用跟踪止损激进地获取利润。情况 3 假设信号是正确的,但预计会出现突然反转:

  • 情况 1:无跟踪止损:你将止损设置为 108:空头 10,000 股。你假设其中任何波动都是噪音,不想频繁交易。

  • 情况 2:激进的跟踪止损:你从 101 跟踪止损计算你的头寸规模:空头 33,000 股。你假设信号足够有效,并希望尽可能多地捕获利润。

  • Case 3: 探索性头寸:你从 108 计算头寸大小,但在 101 设置了一个追踪止损:空仓 10,000 股。 由于没有太多证据表明市场已经转为熊市,作为一名谨慎的风险管理者,你使用固定止损来计算头寸大小,但使用追踪止损来保护你的资本基础。

可以说,大多数市场参与者会选择案例 1 或案例 2。 要么设定一个止损并让头寸自然运行,要么操作交易,这是两个明显的选择。 假设你的入场价是 98。 现在我们已经设定好了,让我们来看看价格走势。 市场在下跌到 96 之前很好地保持,然后改变主意,决定突破 108 的水*。 追踪止损已经下移至 99,因此在案例 2 和案例 3 中,你在 99 处*仓。 在案例 1 中,你在 108 处*仓。

案例 1 案例 2 案例 3
风险预算 100,000 100,000 100,000
成本 98 98 98
位置止损 108 101 108
股票数量 -10,000 -33,333 -10,000
退出价格 108 99 99
盈亏 -100,000 -33,333 -10,000

让我们分析所有情况:

  • Case 1: 这是基本情况。 信号实际上是一个假阳性。 有得必有失,人生如此。

  • Case 2: 在从追踪止损计算头寸大小时,止损实际上锚定在噪音带内。 这是对信号的统计有效性和市场体制的假设。 对于策略有效,市场必须下跌。 如果市场横盘交易,将会有很多失败的尝试,这些尝试的累积效果会侵蚀资本基础。

  • 案例 3:首先,固定止损设置在一个逻辑位置。 如果价格创出新高,那么市场显然已经决定重新进入牛市领域。 这与案例 1 一致。 其次,当头寸最脆弱时,追踪止损保护头寸。 每次有利的价格变动都会降低风险。 当它不起作用时,大部分风险会被结晶为接*盈亏*衡的小损失。 它不会像案例 1 那样发展成全面损失。 第三,在针对上限确定头寸大小时,你实际上已经采取了一个小的探索性头寸。 你已经在桌子上放了一枚筹码,但你还没有准备好叫市场的底牌。 如果它正确地检测到趋势,初始头寸可以被补充。 如果不是,损失将受到控制。 案例 3 是处理随机性并保护资本的有效方式。 相比之下,在案例 2 中,每次失败的尝试都会损害你的资本。 案例 2 正是趋势跟随者最终在横盘市场中放弃收益的原因。

这里没有对与错。目标不是给你提供一种可以简单编码的策略,而是让你以盈亏分布的方式思考。前面的例子只是处理随机性的众多方式之一,即减少误判的拖累。目标是尽可能地将损失峰值靠*保本点。对于自由裁量市场参与者,未来章节概述的“两个部分的游戏”是一种系统化的方法,可以将损失保持在较小水*,以换取利润。

技巧 3:两个部分的游戏:时间退出和如何减少免费骑车者

如果你是一栋建筑的房东,你会允许一些租户免租吗?几个月拖欠租金后,你会赶走那些不付费的人,因为这会损害盈利能力。这种常识性方法并不适用于股票市场。每个投资组合都有其一定比例的存量持仓,它们拖欠租金。

一个经典的误解是,绩效下滑是因为几次大的灾难。深入分析揭示了许多免费乘客的累积权重给绩效带来了拖累,最终未能弥补几次打击。一个“次优的α”经常发生是因为一堆“曾经是英雄”的人仍然阻塞着投资组合。

最常见的类型是“曾经我们是战士”的老兵。他们曾经做出过贡献,但已经有一段时间没有进展了。由于嵌入式的盈亏和情感依恋,他们特别难以发现。这是固定偏见的一个有趣且可以争议的表现。当入场成本远离当前价格时,我们会将当前*淡的回报视为暂时的。在许多情况下,我们应该对投资组合中的所有股票保持这种冷静。然而,同样的“放任自流”的态度会滋生危险的自满。市场参与者有时最终会在采取行动之前将大量纸币利润退还出去。

一个简单的解决方案是引入时间加权收益。如果一只股票在一段时间内未能赚取应有的回报,其权重应该降低。这是一个简单的三步过程:

  1. 决定持续时间。犹豫时,计算年度周转率并除以 3,取第一个三分之一作为持续时间。例如,周转率为 1 将产生一个 4 个月的期间。

  2. 计算第 1 步期间的股票回报(而不是绩效归因)。将其分成四个四分位数。关注第三个四分位数。第一和第四个四分位数脱颖而出。所以,无论如何都会处理它们。第二个四分位数的股票不是出色的贡献者,但它们仍然支付租金。第三个四分位数的股票问题在于它们并不显著。它们是慢慢拖累绩效的死钱。

  3. 将第三个四分位数中所有股票的权重减半。复杂的规则容易违反。所以,保持简单:没有贡献,将分配减半。

其后可能会发生两件事情:

  1. 股票重新表现:添加一个新的分段。

  2. 股票持续低迷甚至表现不佳。实现利润将显得先见之明。处理一个更小的仓位总是更容易的。

将你的投资组合想象成你的房子。你在一个地方居住的时间越长,你就会随着时间累积更多的东西。总会有一些小东西你因为感情上的价值而留着。例如,如果你对你那件宽大的老大学毛衣有迷信或者感情依恋,那么很可能你在职业上也是一位“感情价值”投资者。股票在投资组合中停留的时间越长,它们就越粘稠。我们内心的白痴总是会找到各种理由来用心理捷径来合理化旧仓位,比如“我要买什么替代品?”或者“这个股票一直表现得非常好,它会回来的。” 这个游戏提供了克服最初的不情愿的客观规则。第一步总是最难的。一次减少陈旧仓位将使下次处理它变得更容易。

其次,它使投资组合流动起来。正如市场格言所说,“你的下一个想法决定了你的成败。”强制性地将陈旧仓位清除出去,为新想法腾出空间。受先进先出FIFO)规则约束的市场参与者自然不愿意放弃旧仓位。处理陈旧仓位的另一种方法是使用期权策略覆盖基础现金头寸。请记住,随着时间的推移,你会经常犯错,所以处理今天的亏损将使明天的利润看起来更大。赢家自会照顾自己。你的工作是照顾失败者。现在我们已经处理了分配的失败一侧,接下来我们将考虑方程式的利润一侧。

技巧 4:利润方面:通过获取小利润来降低风险并复利回报

"George,你就这点本事吗?"

—— 穆罕默德·阿里,史上最伟大的拳击手

减少仓位以减少风险的想法对于来自多方的市场参与者来说有些陌生。他们希望通过“起起落落”来持有获利头寸。在空方, “起起落落”被称为熊市反弹和空头压力。有一天,市场参与者舒适地坐在空头上,用巴里·怀特(Barry White)浑厚的男中音声音哼着“永不放弃”。

第二天,他们被迫在脚尖上喘气,用巴里·吉布(Barry Gibb)尖细的假声音哼着“保持活力”。接下来的技巧将进一步超越免疫熊市反弹。与游客空头卖方不同,这项技术将教会你如何欢迎空头压力。

如果你不从中获利,当不可避免的熊市反弹来临时,你的心理状态将处于不利地位。利润将迅速蒸发,你内心的白痴会骗你去*仓以保护剩下的任何利润。这样做,空头*仓将为反弹增加燃料,从而导致不利的执行。另一方面,如果你提前减少风险敞口,你将处于更好的位置来应对反弹。你已经实现了一些利润,减少了你的风险,即使它达到了你的原始止损,你也保证了交易的盈亏*衡。你的情感资本的损耗与职位规模成正比。现在,你有银行里的钱。你有一个几乎没有影响 P&L 的小赌注,可能会为随后的活动提供资金支持。

提前收益可能会减少风险,但也会大大削减利润潜力。与此同时,被止损的交易每次都会造成一个完整的风险单位。如果做得不好,GE 注定会迅速变得负面。

让我们回到 GE 来解决这个方程:

接下来,让我们去掉胜率和亏损率,只关注盈亏*衡,当R = 成本 – 止损X = 价格 – 成本N = 要关闭的职位的比例时:

为了达到盈亏*衡,需要关闭的职位部分是成本到止损的距离的倒数(以 R 表示)。

图表

图 7.3:价格向有利方向移动时需要关闭的职位的比例

简单来说,职位越早被减少,需要关闭的部分就越大,反之亦然。然后它变成了与机会的舞蹈:我们应该让职位运行更长时间,还是在我们可以的时候兑现?当我们使用这种分数退出重新引入胜率时,GE 方程现在看起来是这样的:

我们最初删除了胜率亏损率以集中精力于盈亏*衡。这只是说,职位越早关闭,剩下的部分就越小。现在,市场并不总是对参与者友好。把每个职位看作两个独立的交易:一个大的优惠券和一个小的彩票。第一笔交易需要有一个大于 50%的高概率。它的持续时间和距离都很短。第二个是无风险的彩票。有时它会永远持续下去,有时会以成本关闭。

这里还有一个额外的提示,也是吃了苦头学到的。胜率不是恒定的。为了达到盈亏*衡并至少保持中性交易优势,你可以要么拿出更大的部分,要么更早关闭。你拿出 75%而不是 67%,或者你在 1.5R 而不是 2R 时*仓。然后,盈亏*衡公式变为:

如果损失% > 盈利%,只需关闭更大部分或提前退出。赚钱现在简化为具有高于损失率的盈利率。现在我们知道了距离和部分退出之间的关系,让我们比较一次退出和分批退出之间的 GE。

让我们举一个简单的数值例子。假设我们的策略在 1R 时有 60%的盈利率,或成本到止损距离的 100%。为了练习,假设每增加 0.1R,盈利率就降低 1%:移动越大,频率越低。这是下图中的黑线。盈利率的降低是线性的(每 0.1R 下降 1%):

图表

图 7.4:规模化 GE

让我们计算 GE,假设我们关闭 100%的头寸。这是标记为 GE All-Out 的长弧线。GE 遵循一条弧线。大幅移动是罕见的,最终无法弥补损失。在这种情况下,盈亏*衡率为 16%的胜率和 5.4R 的风险/回报比率。

接下来,让我们计算交易关闭部分的 GE。这是 GE 部分退出线。它以线性方式跟随胜率。随着价格超出 2R,成功概率下降到 50%以下。单独部分退出的 GE 机械性地变为负值。请注意,此部分退出仅作为视觉参考,因为剩余部分是无限期开放的。趋势跟随策略通常具有默认负的 GE。大幅移动是罕见的。损失控制确实是确保长期 GE 保持正值的唯一方法。

最后让我们计算一个部分退出和剩余部分的 GE。我们设置四个目标价格分别为 1.1R、1.5R、2R 和 3R。我们分别关闭 91%、67%、50%和 33%。剩余部分被关闭。部分退出显著改善了 GE。1.1R 是最保守的。它具有最低的回报潜力,但内置了稳健的 GE。1.5R 具有更高的回报潜力,但剩余 GE 较低。在这个例子中,2R 和 3R 的终端负 GE。过了某一点,剩余部分就像是一张彩票。

风险降低遵循两个规则:

  1. 盈利率 > 损失率:有时候盈利率暂时较低。然后,要么提前关闭以改善盈利率,要么关闭更大部分以减少风险。

  2. 目标价格 > 1R:利润必须大于损失。

故事的教训是,市场参与者最好在 2R 以下关闭更大部分。这提供了稳健的 GE。稳健的期望值保证了更大的头寸规模。

但是,在设计稳健策略时,这种游击交易方式并不是自然而然地出现在脑海中。对于部分退出的反驳是,止损必然会很昂贵。提前关闭交易会削减其利润潜力。与此同时,失败将耗尽全部风险预算。似乎交易优势注定是负的。此外,直觉上分批出局感觉就像是把钱留在了桌子上。事实上,绝大多数市场参与者更愿意集中精力改善他们的信号,而不是努力改进他们的订单管理。

大多数市场参与者都是从全进全出的模式操作的。他们漫步进入,有时补充,然后一次性狂奔出去,所以退出是一个单一事件。市场参与者可能会发现,当他们开始工作时,他们不愿意大幅度减少自己的头寸。请记住我们在玩一个无限的游戏。目标是设计出一个稳健的 GE。这让我们想到了一种称为凯利分批出局组合(暂且这么称呼)的扩展技术。这个主题的一个更激进的变体是利用高胜率来超级化头寸。

正如我们在整本书中看到的那样,退出政策决定了策略类型。让股票运行的趋势跟随者拥有不频繁的大胜利。持反对意见者有频繁的小胜利。由于退出决定了分布的形状,因此可以通过简单的分批出局来结合两者的属性。

均值回归 趋势跟踪 混合
胜率
波动性
左尾部
右尾部
偏斜

这个概念是要大幅度进入市场,关闭大部分交易,并让剩余部分无风险地运行。高概率的早期部分退出将模式,即交易峰值数量,带到了利润方面。如果胜率超过 50%,甚至可以使用像分数凯利或拉尔夫·文斯的最佳 F这样的公式来超级化头寸。最佳 F 是另一种强大的头寸大小算法,它考虑了最大回撤。这保证了大头寸。这些是快速交易。它们以几何速率快速复利。这意味着我们大举进入,赚一笔快钱,关闭大块,然后将这笔钱重新投入流通,如此往复。

让我们回到我们的假想例子来解释这个过程。假设是,胜率每增加 0.1 个单位,就减少 1%。凯利准则是一种投注大小的算法,我们将很快在下一章中重新讨论。在 1.1R 处退出,胜率为 59%,这支持每笔交易 18%的风险。

R(距止损单位的距离) 胜率 凯利全出 部分退出数量 剩余
1.00 60% 20% 100% 0%
1.10 59% 18% 91% 9%
1.20 58% 16% 83% 17%
1.30 57% 14% 77% 23%
1.40 56% 12% 71% 29%
1.50 55% 10% 67% 33%
1.60 54% 8% 63% 38%
1.70 53% 6% 59% 41%
1.80 52% 4% 56% 44%
1.90 51% 2% 53% 47%
2.00 50% 0% 50% 50%
2.10 49% -2% 48% 52%

让这些百分比沉淀一秒钟。如果“做大做全...提前回家”实际上是一种成功的策略呢?例如,假设您将目标价格设定为 1.5 倍风险。胜率舒适达到 55%,因此根据上表中的凯利列,您可以每笔交易承担 10%的风险。您所需要做的就是在 1.5 倍风险处关闭 67%的仓位,然后将止损重置为成本。剩下的 33%是无风险的彩票。有时您会获得 2 倍风险,有时您会获得 5 倍风险。最坏的情况下,您以成本价*仓。

让我们再次回顾以加强论点。第一笔交易是短期、高胜率、大规模仓位,将模仿均值回归分布。这笔交易感觉像剪下优惠券,因此被称为剪票。第二笔交易是一张小彩票。一旦第一笔交易关闭,将止损重置为成本(绝对或相对),然后就可以放心地持有到交易结束。这笔交易本质上具有更多的随机回报,因此被昵称为彩票。

图表

图 7.5:凯利比例组合

该图基于前一个图表。它包括仓位大小。请记住,投资者始终会在下跌时下意识地做出反应,即使他们在意识上说他们想要回报。因此,提前关闭不仅是明智的,而且是提高资产管理规模的关键。结合均值回归和趋势跟随策略的盈亏分布形状如下:

图 7.6:结合均值回归和趋势跟随策略盈亏图

交易的模式在盈利方面(胜率高)。这与均值回归策略一致。交易的分布偏向右侧。这是趋势跟随者的右尾彩票。

这是一种利用高胜率和大数定律的强大方式。这样可以使资本基础复利增长,清除失败,并补贴未来的交易活动。由于存在连续亏损、暴露限制,尤其是投资者的*静睡眠需要保护,因此不建议进行大规模的凯利交易。正如我们之前看到的,投资者对回报的关注不及对回撤的关注,因此总是明智地偏向保守。在接下来的章节中,我们将看到一种动态的分数凯利方法,将有助于减轻回撤风险。

让我们回顾一下什么是分批出局,即有纪律的止盈所能达到的目标:

  • 复利小利润:均值回归市场参与者通过复利小利润赚取他们的钱。风险降低合成地也是在做同样的事情。小利润迅速复利。

  • 其次,"卖空并期待"策略的支持者总是声称他们能看透短期的波动。这是正确的,直到他们第一次遇到波动。如果你已经关闭了一部分头寸,降低了风险,实现了一些利润,并确保你将在交易中保持盈亏*衡,你将处于更好的心态来应对熊市反弹。在实践中,你可能会如释重负地看到最终看到熊市反弹重新进入游戏并增加另一笔交易。

  • 第三,它给利润与损失分布的利润方向提供了另一种模式和正的偏度。这种利润模式是为了补偿损失方向上的模式。换句话说,那些累积的小利润是为了吸收大部分损失。

当你考虑建立一个交易优势时,这可能不是你想到的。剪券是费力而不性感的,但它也是一种有效的方式来倾斜交易优势,并快速复利。

实际上,如果你足够勤奋地练习这种降低风险的方法,你会训练你的大脑期待那些熊市反弹成为乘胜机会。当其他人都在防守时,你实际上正在进攻。

技巧五:延长右尾

"你不必用力挥动球棒才能击中一支全垒打。如果你抓住了时机,它就会飞出去。"

——尤吉·贝拉

移动止损非常适合保护资金,但它们只在完美的条件下起作用。因此,它们的有效期有限。一旦风险降低,保持移动止损可能会触发过早退出。移动止损的目标仅仅是将损益分布倾向于接*盈亏*衡。现在剩下的部分不再承担风险,你可能想要取消移动止损,依靠你的固定止损。空头方面的波动性很高。给市场一些回旋余地,直到是重新进入的时候。

我们都在挣扎着说最后再见。我们成为了对我们的赢家有"情感价值投资者"。我们都倾向于推迟不可避免的事情。此外,基本面新闻的流动在价格行动开始朝相反方向移动后仍然支持我们的论点。往返旅行并不罕见。

市场参与者真正需要的是一个客观的信号,表明趋势已经结束。地板/天花板法则足够稳定,可以使市场参与者稳固地度过市场上的困境。作为一个普遍原则,最终的退出应该是趋势的逆转:股票留在投资组合中,只是换边。

传统智慧说,你在写入场之前不能写出场的“书”。从空头方面的经验表明不然。如果你先建立好逃跑路线,那么入场只是滑动的概率。例如,在熊市反弹转向后进场,成功的概率和持仓规模都比等待新低要高。出场就是当纸上利润变成真金银。然而,在我们对最后一种技术的讨论中,我们将讨论每个人最喜欢的话题:入场。

技巧 6:重新进入:通过分级头寸来乘坐你的赢家

“你、我,或者没有人会像生活那样打击你。但问题不在于你被打击有多猛烈。而在于你能被打击多么猛烈而不倒下。”

——洛基·巴尔博亚(Rocky Balboa),意大利雄鹿

在 20 世纪 80 年代初,海龟交易员尽管只有可怜的 34%的胜率,但他们赚了数亿美元。他们的秘密武器:他们加仓了他们的赢家。长期参与者和卖空者之间的主要区别之一是定期补充成功头寸的必要性。随着利润增加,卖空头寸会缩水。因此,在长期方面盛行的全仓/空仓方法在空头方面失败了。在某个时候,你需要补充你的成功空头。当你增加你的赢家时,你的胜率和*均盈利都会提高,这从机械上提高了你的交易优势。

重新进入(Re-entry)确实是该策略展现其加速潜力的地方。你已经有了合格的赢家,赚了一些钱,并降低了风险。熊市反弹已经在你的止损线下方转向。买入压力已经耗尽。现在有足够的证据表明熊市行情已经开始。游客已经被清除出局。借贷甚至可能更容易一点。星星们为光荣的第二轮准备就绪。

不幸的是,对于犯有TWA(“交易当美国人”)罪行的市场参与者来说,逐步加仓和减仓是不可能的。美国实施了一种称为 FIFO 规则的库存估值方法,规定所有仓位必须从最旧的减少到最新的。这实际上阻止了美国参与者围绕他们的头寸进行交易。

在我们进一步探讨之前,这里有一个关于在熊市抛售期间逐步加仓的重要提示。随着市场暴跌,逐步加仓是很诱人的。然而,大多数市场参与者是为了买入而不是卖出。这使得卖空者处于自然劣势。假设某处的某人一直在等待这种弱点作为购买机会。这意味着一旦卖出压力消失,长期参与者将推高价格并触发卖空止损。以较低价格进行的第二笔交易很可能陷入交叉火力。好消息是:如果卖空仓位得到验证,那么市场将在下一次熊市反弹时再次给你进场的机会。耐心是一个有利可图的美德。

首先,重置你原来仓位的固定止损。有几个合理的位置。更激进的版本是将其放置在当前熊市反弹水*的峰值之上。这将保护利润,但会受到波动冲击的影响。最保守的版本是将止损设置在之前的成本位置。在这两者之间的某个位置是“法国式止损”。市场在摆动高点和低点上下波动。这给市场一些额外的摇摆空间。这将需要更小的仓位规模。如果趋势逆转,你甚至可能放弃更大部分的利润,但你会晚上睡得更好。这个止损被延迟了一个摆动,因此被时髦地称为“法国式止损”。

一旦第一个 tranche 上的风险降低,就是重新使用与之前相同策略的时候了。重新进入空头仓位的最佳时机是在熊市反弹或空头挤压之后。游客们被迫*仓。买压正在消失。如果当前顶部低于前次入场的顶部,则卖家仍然控制着局面。重新入场的条件不需要像初始入场那样严格。然而,重新入场必须满足三个条件:

  1. 趋势是你的朋友:当前的入场价格必须低于上一次的价格。市场参与者有时会被诱惑以比上一次更高的成本重新进入。这是贪婪露出丑恶的一面。这样做有效,直到不再有效。有一天,它会感觉像是饮过龙舌兰酒后的早晨:“当时,这似乎是个好主意。”更高的入场价格可能是市场即将 consoldate 或逆转的早期迹象。

  2. 借用利用率必须低于 50%:借用利用率被定义为可供借用的股份除以已借出的股份。这是对供求关系的最简单的监测方式,也是最有力的表达方式。随着长期持有者的清算,可供借用的股份的供应减少。与此同时,随着空头卖家的涌入,需求增加。空头卖家通过跟随多头卖家赚钱。当借用利用率上升到 50%以上时,意味着长期持有者已经离场,剩下的只有游客。在交易变得拥挤时增加另一个 tranche 是在自找麻烦。你将不再是跟随多头卖家,而是被困在空头卖家的试管中。在多头方面,新的买家会抬高价格。在空头方面,新空头卖家的供应受到可借用的股份的限制。因此,他们没有能力推低价格,但他们增加了卖出压力,使股票易受到空头挤压的影响。

  3. 对于每一个新仓位降低风险:在现有仓位上加仓被称为金字塔加仓。记住,趋势最终会逆转。随着趋势成熟,趋势逆转的可能性增加。

将所有持仓的固定止损重置为“法式止损”,即接*之前进入市场成本的某个位置。当您降低旧头寸的止损时,无论接下来发生什么,它们都将是盈利的。这种内在的盈亏将资助更多的新头寸和风险较高的头寸。增加成功头寸会提高胜率和*均盈利。

所有美好的事情最终都会结束。如果因为被挤兑或者被摇摆出局而辛苦工作的交易最终以失败告终,那将是一种遗憾。

最终退出:右尾

趋势跟随者喜欢在其头寸上“骑着夕阳”前行。有时他们会,在多头市场。而在空头市场,要想获得 2-3 倍的收益,需要更多的技巧,因为向下的潜力被限制在 100%。

最困难的任务是放弃一笔成功的交易。总会有这样一种烦人的想法,认为这可能是暂时的,还有可能有更多的机会。还有就是害怕失去太多业绩。这可以分解为两个独立的问题。市场参与者需要一种客观的方式来知道何时趋势已经结束。其次,如果不稳定性只是暂时的,那么他们需要一种重新进入市场的方式。

第五章市场环境定义中,我们描述了地板和天花板法。理由很简单。牛市在所有摆动高点低于峰值(天花板)时结束。熊市在摆动低点高于谷底(地板)时结束。地板和天花板法是定义趋势何时结束的客观方法。当打印出新的地板时,退出所有空头头寸。记住,您将会放弃一些业绩。使用这种方法,您不是在试图时机的顶峰,而是支付确认趋势已经结束的代价。

最终退出后的重新进入

市场并不总是按预期行动,有时您会被迫退出某个头寸。如果市场再次表现出期望的行为,您会希望重新进入市场。最初进入市场的条件不太可能再次满足。例如,如果你做空了一个昂贵的价格收益比PBR)为 2 的股票,当前的估值可能已经下降到基本公*价位附*。因此,你不会再进入这笔交易。因此,您需要一些简单而强大的方法来重新进入市场。

这就是地板和天花板法的作用。如果您因为价格打印出一个地板而被摇摆出局,但随后却打印出一个天花板,那么重新进入市场。将止损设置在天花板水*,验证借入资金是否仍然合理,然后开始。关于空头头寸的一个重要经验教训是,它们的下降并不总是线性的。股票从过高的价格下跌到公允的估值。它们有时会吸引多头参与者,然后恢复下跌,进入价值陷阱的空头天堂。给自己一些重新进入市场的灵活性。

趋势跟随者占据了市场参与者的绝大多数。接下来,让我们看看均值回归参与者是一种罕见的品种,他们面临着自己一套挑战。

如果您的主导风格是均值回归,如何倾斜您的交易优势

"赐予我割掉失败者的宁静,勇气骑在赢家身上,以及辨别两者区别的智慧。"

– 交易者的宁静祈祷

均值回归策略具有负偏态,利润端的众数:右尾偏短,左尾偏长。解决方案是缩短左尾,延长右尾。

均值回归市场参与者天生擅长卖空。他们在高点卖空,在低点补回。他们也更擅长应对横向市场。然而,主要危险是忽视市场环境。虽然诱人的是卖空高估值或超买的 RSI,但处于上升趋势的股票往往会继续其上升轨迹。例如,RSI 会在牛市股票上从 40 上升到 80,在熊市股票上从 60 下降到 20。超买和超卖条件通常是持续性的迹象。

解决方案是等待市场环境从牛市转向横盘或熊市,然后开始卖空。在分析中纳入市场环境定义方法,如 Floor/Ceiling 或移动*均线交叉,以减少误报。

损失

与均值回归策略相关的风险在于尾部:一些巨大的损失。均值回归市场参与者不喜欢止损。它们有时会在股票开始表现如预期之前触发。胜率下降,*均损失上升,期望值下降。一种方法是使用更宽的止损。它们将需要更小的头寸,但也将防止灾难性损失。

均值回归市场参与者经常会受到诱惑,在失败头寸上增加头寸的前提是它们最终会回归。例如,如果股票预期在均值的 2.5 个标准偏差处回归,那么在 4 个标准偏差处,它甚至更具吸引力。这种做法大多数时候是有效的,但是当它失败时,损失可能是毁灭性的。LTCM 曾试过这样做。马丁·盖尔方法有效,直到它不再有效。

一个在统计上更健壮但违反直觉的方法是在市场参与者感觉应该增加头寸时减少头寸。假设过了某个阶段,非有效性不会纠正而会持续存在。如果在 4 个标准偏差处减少头寸而不是增加失败者的话,那么要么它会回归并抵消损失,要么之后减少的损失会更少。无论哪种方式,它都会将损失的偏态倾向于趋于*衡。

另一个市场参与者应该减少而不是增加亏损头寸的实际原因是通用电气的恶化。增加一个失败者直接增加了损失率和*均损失。通常情况下有效,直到它崩溃。

利润

均值回归市场参与者往往会过早退出。深度价值投资者经常将接力棒交给增长管理者,然后他们将股票骑到兴奋的地步。他们留下了利润。

更重要的是,它们具有不利的尾部比率。需要许多小胜利来弥补一次大损失。均值回归市场参与者需要延长他们的右尾。

因此解决方案是关闭一部分仓位,让剩余仓位使用不同的退出机制运行。

部分退出

使用先前显示的部分退出公式(N = 1/X)来计算您需要关闭的确切金额,使交易保持盈亏*衡。如果有疑问,关闭仓位的二分之三到四分之三之间。高胜率加上超过 50%的利润收割,保持了盈利引擎的持续运转。

对分布的影响将使得利润方面的模式更接*保本。胜率不会受到影响,只有*均获利受到影响。

退出

趋势追随者需要确信需要一路盈利。均值回归市场参与者需要被说服他们应该推迟最终退出。问题在于价值投资者不是被理性地解释成长的。部分退出后,剩余部分将在以后的某个日期使用不同的退出机制关闭。以下是两种方法:

  • 均值周围的低效率:均值回归意味着围绕一个均值的振荡。因此,在均值处关闭仓位是不必要保守且有些不合逻辑的。在关闭仓位之前,等待价格在另一个方向上超调。这种超调不必是对称的。例如,一个 2.5 个标准偏差的移动可能会导致进入,但全仓退出可能会发生在 1 到 1.5 个标准偏差之间的某个位置。当估值下跌时,它们通常不会停留在市场*均水*上。它们会在稳定之前超调。这种方法与均值回归市场参与者的心态更一致。低效率存在于两个方向。

  • 波动性跟踪止损:第一种方法是设置一个波动性跟踪止损,通常称为吊灯止损。将一定数量的*均真实范围添加到最低点。当价格关闭超过止损时,关闭仓位。这个技术借鉴了趋势跟随策略。

将右尾延长视为那些毁灭性损失的解药。你允许你的持仓多跑一点时间,下一次恢复所需的时间就会减少。

总结

随机性无法根除。所以,停止自欺欺人地假装预测任何事情。当市场波动时,那些为投资者制作柠檬水的人会继续经营下去。

在这一章中,我们首先考虑了退出一个位置的心理影响,以及一些克服你不愿意止损的步骤。然后,我们探讨了六种可以提高你交易优势的技巧。其中五种涉及退出,一种涉及进入,目标是缩短左尾和延长右尾。通过裁剪失败者并让赢家超出你的舒适区,来实现这一目标。

接下来,我们将考虑任何战略的另一个重要部分——头寸规模。

第八章:仓位大小:财富创造在金融管理模块中

传奇投资者一直强调同样的事情:风险管理是长期优异回报的关键。挑选股票很性感,但大大被高估了。风险管理很无聊,但大大被低估了。在执行交易员的英语中,市场专家们专注于拣选正确的原料,而不是关注拿到正确的配方。

在一天结束时,长期几何回报的主要决定因素是仓位大小。长头寸的扩张并不迫使市场参与者考虑仓位大小。毕竟,一只好的 AAPL 股票可以让一篮烂苹果看起来很好。尽管有糟糕的仓位大小算法,他们仍然能够存活。卖空者没有对数价格下降的奢侈。在本章中,我们将考虑一些糟糕的仓位大小算法的经典示例。这些就是末日定位大小的四骑士。

在我们仔细研究了常见的陷阱之后,我们将考虑一种不仅有效,而且能够最大程度减少糟糕决策影响的策略。

我们将涵盖以下主题:

  • 导入库

  • 末日定位大小的四骑士

  • 仓位大小是情感资本和财务资本之间的联系

  • 比较仓位大小算法

  • 优化您的风险预算

你可以通过以下链接访问本章节所有图片的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。你也可以通过本书的 GitHub 仓库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

对于本章和本书的其余部分,我们将使用pandasnumpyyfinancematplotlib库。所以,请记得先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt 

末日定位大小的四骑士

"只听取你想要成为的人的建议。"

– Gilbert Bernut,父亲,超级英雄,不为人知的 20 世纪哲学家

在富达期间,我经常运行我的算法跨其他经理的投资组合。我无限的野心是通过每次提高 0.01% 的业绩来帮助我的同事。虽然看起来不像什么,但即使每笔交易的基点在一年内复利也足以将排名从第二分位数提升到最高分位数的稀有气候。

很快,我意识到同样的股票在所有投资组合中不断出现。将聪明、充满激情的人聚集在一起,在同事之间形成健康的交叉传粉是很自然的。

更引人入胜的是,尽管持仓的分散度很低,但表现存在差异。人们预期相似的持仓会产生相似的表现。然而,无论是表现还是跟踪误差(即回报的波动与基准相比)都存在差异。由于大多数投资组合中都存在同样的问题,所以股票选择显然不是绩效的主要驱动因素。真正产生差异的是头寸规模。赚钱在于资金管理模块。

现在,股市赚钱的悖论在于:能够赚钱的模块也是策略中最无聊的部分。每个人都想向世界宣告,他们几年前买入了 Netflix 或 Amazon。然而,没有人会承认他们只有边缘位置,不知道应该买多少股。然后,他们想知道为什么尽管选择了优秀的股票,但仍然表现不佳。

因此,资金管理的纪律被放置在了遥远的次要位置,被视为需要完成的琐事,就像倒垃圾或支付水电费一样。这导致市场参与者宣扬灾难性的资金管理做法。用执行交易员的术语来说,由于无知的赌注规模,通过选股获得的所有潜在收益都被抹去了。

让我们看看目前业界采用的四种最具破坏性的资金管理技术。

马厩主 1:流动性是熊市的货币

“你随时都可以退房,但你永远也无法离开。”

——唱片《加州旅馆》中的 Don Henley

在不流动的股票中持有大头寸已经使许多才华横溢的基金经理陷入困境。小市值股票和不流动的股票就像船只和豪华玩具。你随时都可以买,但你永远也无法离开。如果你不能在不损害市场影响的情况下退出一个持仓,那么你不是持有它,而是被它拥有。

流动性是熊市的货币。当“救赎之歌”开始奏响时,管理人员被迫清算他们能够清算的任何资产,而不一定是他们想要的资产。

这使他们拥有不流动的残骸,从而延续了救赎的恶性循环。小市值股票在熊市中尤其脆弱。流动性消失,买卖价差扩大。在大金融危机(GFC)期间,那些试图从不流动资产中退出的人很快意识到,买卖价差足以让一艘超级油轮毫发无损地停泊。

关于容量的一则附注。投资者的第一个问题之一是容量:一个管理者在收益开始下降之前能够承载多少资产。投资者知道,在最初的几年里,当资金规模较小而管理者渴望时,收益最高。然而,他们想要在扣动扳机之前看到一些业绩记录。因此,他们尽可能地观察等待,但不要过久,以确保他们仍然能够享受到一些体面的回报。更多的是一种数学*似,一个真实的生活中的酸性测试是惯性。当管理者开始因为市场影响而放弃交易时,他们已经达到了饱和点。正如我的导师金正允经常说的:“惯性渗入时,容量就确定了。”如果你发现自己因为惯性而错过信号,而这似乎是正确的事情,那么你要么是懒惰的,要么是你的资产规模太大。无论哪种方式,这都是一个警钟。

马厩 2:*均下去

"失败者总是*均下去。"

  • 保罗·图多·琼斯

*均下去仍然是基本市场参与者中流行的一种方法。随着价格下跌,估值看起来更便宜,因此他们增加了现有的亏损头寸。增加到一个亏损头寸会使交易边缘公式中的四个变量中的三个变差:损失率和*均损失增加,获胜率下降。唯一不受影响的变量是*均获胜,这是任何人都无法控制的。此外,分配给失败者的额外资本必须来自某处。它要么来自现金的新注入,要么来自被截断的盈利头寸。总之,*均下去可以总结为:“削减你的赢家,运行你的输家。”成功的秘诀难道不是:“削减你的输家,运行你的赢家”?

金融服务行业充斥着由一系列后测验、优化和令人昏昏欲睡的白皮书支持的晦涩理论。与其停留在抽象的世界中,评估它们的有效性的一个简单方法是与现实世界进行类比。在赌博世界中,*均下去被称为马丁内尔。每个新手赌徒都想出了一个打算打破赌场的方法。在每次失败后加倍下注,然后你最终会拿回你的钱。首先,这种策略忽略了连续输的理论。

长期来看,抛硬币有 50%的概率。然而,结果并不是头和尾的整齐交替。每一次抛硬币都是独立的。有时候,头可能连续出现 8、9 或者 10 次。这前提是有无限资本。其次,最有利的结果是*手。这意味着在这之前的任何结果都有一个有趣的统计属性,称为破产的确定性。总的来说,赌场为什么有大理石、画作和免费酒,而新手赌徒却开着破旧的车回家,其中有个原因。

如果加权*均法在统计上显然是破产的,那么为什么它在专业投资者中仍然如此受欢迎呢? 在他引人入胜的自传一位适应所有市场的人中,爱德华·索普将加权*均法描述为锚定偏见。 市场参与者在进入头寸的时刻对股票价值做出了假设。 价值是他们赋予估值的主观意义,或者正如沃伦·巴菲特所说:“价格是你付出的代价。 价值是你得到的东西。” 随后,他们的判断将始终受到最初成本的影响。 如果一只股票在他们以 10 美元买入时看起来便宜,那么以 9 美元买入必定是个大便宜。 市场参与者假设他们的分析是正确的,而市场暂时是错误的。 在市场纠正这种低效之前再增加一个标的可能会导致更大的利润。 理论上,这是有道理的。

实践中,“这很复杂。” 当赌注很小时,情感参与保持最小。 再增加一个标的会增加压力水*。 大脑突然从 1 美元的买入跃升到高额赌桌。 以前不存在的一系列情绪劫持了思考大脑。 现在赌注很高,自我不能承担错误。 正如我们在第七章提高您的交易优势中所看到的,随着止损心理学,这里表现出来的自我“需要正确”的心态总是超越了盈利的义务。

传奇投资者强调风险管理的重要性。 他们还谈论在市场面前的谦逊。 市场巫师们是综合长数学和短自我的。 跟随统计上破产的方法的拥护者;短统计数据。 他们还通过加倍下注来打破市场先生的搏。 长数学,短自我听起来像是金融服务行业的短暂职业生涯的配方。

骑士 3:高信念

“我感觉很好!”

– 詹姆斯·布朗,教父

信念是一种由最糟糕的和最好的投资者实践的头寸大小算法。 最糟糕的投资者制定了一个投资论点。 然后,他们以一些“胆量”赌注向世界广播他们的信念:“要么大手笔,要么回家。”

不幸的是,t 统计量,一种统计鲁棒性的度量,不能提供精神上的鲁棒性。 当市场参与者承担大额赌注时,他们失去了客观性。 他们的自我渴望验证。 高信念是一种“感觉良好”的赌注大小,没有统计学的有效性。 当然,那些感觉良好的明显交易很少是最有利可图的。

现在,最成功的投资者也会进行大额、高信心的押注。不同之处在于,他们用风险单位来表达信心。这意味着他们先制定一个论点,首先量化风险,然后根据情况确定头寸大小。乔治·索罗斯以大规模押注而闻名。虽然每个人都记得做空英镑交易,但很少有人知道长期资本管理LTCM)的故事。根据传奇交易员维克托·尼德霍夫,他当时在索罗斯先生的店里工作,通过在 LTCM 危机期间削减损失,他为许多交易员赚取了丰厚的奖金。这些都是经过计算的风险单位。

第四个骑士:*等权重

*等权重是基本股票选择者的重要组成部分。他们依靠自己的股票选择能力来创造业绩。所有的股票选择都大致相同,所以他们不认为需要不同大小的头寸。

投资组合管理不是一种民主行为。*等的机会不会带来毁灭,但它可能阻止你实现长期目标。不是所有的股票都有相同的贝塔值。沉闷的公用事业公司与激进的互联网股票的波动特征不同。通过在头寸大小确定层面忽视贝塔值,波动性会重新出现在投资组合层面。波动性股票将推动整体投资组合的波动性。由于投资者对波动性做出反应,因此建议根据它们的波动性或贝塔值确定头寸大小。在执行交易员的英语中,请记住,如果你给予你的想法*等的权利,那么这将伴随着你的资产曲线的*等左侧。

这引出了一个有趣的问题。机构投资者是否知道有一个最优的头寸大小算法?

头寸大小是情绪和财务资本之间的联系

"这是一个伟大的实验,原因很多。它应该成为任何对金融或赌博感兴趣的人基本教育的一部分。"

  • Edward Thorp,所有市场的超级英雄

Elm 创始人、LTCM 前交易员维克托·哈加尼对 61 名志愿者进行了一项实验,他们是金融界明星学生和老练的投资专业人士。参与者被赋予了 25 美元的起始资本,并被告知在 30 分钟内翻转一枚虚拟硬币,被告知,“硬币有 60%的概率正面朝上,你可以在每次翻转上任意押注,无论是正面还是反面。”你会押多少?似乎有一个公式可以计算最优押注大小,从而最大化长期几何回报。凯利准则的公式是:

def kelly(win_rate,avg_win,avg_loss):  
    # Kelly = win% / abs(avg_loss%) - loss% / avg_win% 
    return win_rate / np.abs(avg_loss) - (1-win_rate) / avg_win 

尽管参与者的背景和所谓的成熟程度都很高,结果却令人大失所望。只有 21%的玩家达到了最高限制。尽管有 60%的胜算,但令人震惊的是,有 28%那些勇敢的、精明的金融专业人士竟然破产了!有些人注定要在被称为管理的破产基金经理的庇护所中寻求庇护…

现在,让我们玩同样的游戏,但这次加大赌注。让我们从你的整个一生积蓄开始。上次,在每次抛掷中,微薄的 25 美元的预期回报在 300 次抛掷后超过了 300 万美元。现在,你知道了赔率和公式。这次,押注你一生的积蓄应该使你遥遥领先于比尔·盖茨、沃伦·巴菲特和杰夫·贝佐斯。

如果这么容易,为什么没有人会那么快变得那么富有呢?原因在于连续亏损。抛硬币没有记忆。每次抛硬币都与上一次独立。即使长期概率为 60%,也会有一些连续亏损的时期。

如果你每次投资都占资本的 20%,你的一生积蓄在连续亏损时会是这样。

地图的特写 图片描述生成的可信度很高

图 8.1:每次押注 20%时的资本耗尽

经历了 3 次亏损后,你一生的积蓄就会减半。经历了 5 次亏损后,只剩下三分之一。在你辛苦积累的一生积蓄(或者在金融专业人士的情况下,不当获得的收益)在不到 1 分钟内被抹去一半后,你还会坚持数学上正确的计划吗?很可能,在某个时候,你的大脑会说停止。

这里有四个重要的教训:

  1. 61 位参与者中只有 5 位知道凯利准则。这对金融课程提出了令人不安的问题。如果学生从未被教导如何下注,他们如何能够赢得一个叫做股票市场的概率游戏呢?教授像有效市场假说EMH)这样的东西就像是在发现青霉素之后长期教授医学生希波克拉底的体液理论一样荒谬。作为对 EMH 的激烈批评者和拥有卓越业绩的对冲基金经理,爱德华·索普写道:“这是一个很棒的实验,有很多原因。它应该成为任何对金融或赌博感兴趣的人的基本教育的一部分。”

  2. 仓位大小决定了任何策略的长期几何回报。押注过于保守,你最终赚的钱会比你本可以赚的少。押注过于激进,你最终亏的钱会比你应该亏的多得多。在交易执行员的术语中,押注过小,你就没有生意可做。押注过大,你将失去你的生意。

  3. 凯利准则或最优 f可能是产生最高长期几何回报的仓位大小算法。这并不意味着专业基金经理应该无条件地采用它们。F1 赛车可能是最快的车辆,但它们不是用来在当地杂货店购买牛奶的。正如我们将在第三部分中看到的,多空游戏:建立一个多空产品,投资者会用回报来换取绩效。因此,市场参与者通常使用分数凯利甚至不太复杂的算法进行交易。

  4. 仓位大小不仅仅是一个数学问题。仓位大小是金融资本和情感资本之间的关键联系。消耗前者将需要时间和精力来重建资本。这是一个复杂的问题,但不是一个复杂的问题。有一个最佳解决方案。另一方面,破坏后者,游戏结束。在实践中,心理学超越了数学。每个市场参与者都遇到过“害怕扣动扳机”的问题,或者在跳水前进行了太多的大赌注。资本保值至关重要,特别是在情感方面。

这恰好引出了下一节。

一个你的大脑能够交易的仓位大小

“我不害怕,我生来就是为了这个。”

– 焦安娜,自由斗士

仓位调整算法是由数学家为心理变态者设计的。他们没有意识到驾驶座位上的内心白痴。我们偏离理性的赌注大小的原因与逻辑无关。在本章开始的偏向硬币游戏中,即使在第二次连续失败之后,你可能会更加保守地押上你的生活积蓄,尽管理性的选择应该是在整个实验中坚持下去。

焦安娜是法国的自由斗士,也是英国脱欧的原始发明者。在 16 岁的嫩龄时,她想到了将英国人赶出法国王国的主意。在法国人的集体想象中,焦安娜被记住了两件事。第一件事是如此悲剧性,以至于持续困扰着法国人的心灵。

她被俘虏、拷打,并最终在鲁昂的一个公共场所被烤了。并不好,但再次提到中世纪总是有点中世纪。其次,她以听到声音而闻名。当股票开始在投资组合中钻出足以开采页岩气的深坑时,我们的内心焦安娜醒来。我们开始听到声音。我们被恐惧所麻痹。皮质醇液淹没了前额皮质,或者说“思考大脑”,我们错过了甚至是“免费赚钱”的交易。

总之,我们的内心白痴只理解两种仓位大小:太少或太多。当一切顺利时,永远不会有足够的好东西。当似乎一切都不顺时,总是有太多的坏事。

这让我们得出一个重要的观点:风险必须有界限。

确定风险区间

风险需要在最小值和最大值之间波动。这些边界可以是上限的凯利系数的一小部分,比如 30-50%。变量上限的好处是流动性。除非你试过,否则你不知道你的系统能承受多少风险。也许你承担了太多或太少的风险。两个考虑因素:波动性是集中度、头寸数量的函数,而头寸数量本身是每笔交易的风险的函数。如果你的目标是拥有多样化的低波动性投资组合,限制上限可能是明智的。

另一方面,较低的带可以是严格的最小值,比如 0.10%-0.15%。确保你的系统在连续亏损期间继续交易。可变的下限带可能导致负面仓位大小。这会导致交易暂停。如果系统不能产生新的交易,它就不能摆脱困境。

我们内心的白痴总是在市场顶部赌博太多,而在市场底部冒太少的风险。我们都曾经历过这种情况。停止疯狂的方法是在内心白痴醒来之前让大脑思考。做到这一点的方法是设定边界:

  • 最小风险:如果你不购买至少一张彩票,那么中彩票将不容易。你必须继续交易以摆脱回撤。经典的“害怕扣动扳机”实质上是一个仓位大小问题。有一个足够小的大小,你会说“嘿,为什么不呢?”最小风险介于系统运行的最小大小和“害怕扣动扳机”出现之间。

  • 最大风险:这取决于你的投资者的风险偏好。当他们说他们可以忍受-20%的下跌时,他们实际上是说你将进入一个鲍勃·马利市场,也就是“救赎之歌”,在-10%的回撤之后。

    无论你认为你的投资者的容忍度可能是多少,这个数字的三分之一是一个不错的*似值。最大风险也是股票数量和*均赢率的函数。

如果你的策略保持在这些限制范围内,它将是安全的。下一步是建立一个传输系统,使你能够在最小和最大风险之间切换档位。

在这一关键时刻,我们理解需要将市场的一些反馈机制纳入我们的风险偏好中,这将引导我们进入下一节。

股权曲线振荡器 – 避免经典股权曲线交易的二元效应

你会怎么看待一个只开一档挡的人?几乎不可能获得诺贝尔奖。欢迎来到金融服务行业,在这里天才们通过牛市和熊市都把他们的投资组合开到一档或五档。持续风险就像一辆被卡在一档挡的兰博基尼一样有效。当你的风格奏效时,承担更多的计算风险。当它不奏效时,专注于资本保护。

根据绩效调整风险称为股权曲线交易。经典的股权曲线交易使用方法,如移动*均线交叉或突破。当股权曲线穿过移动*均线或创下新高时,风险会从胆怯转向大胆。

这种方法滞后于市场。它衡量的是从一个股本水*的前进。例如,当股本水*从 100 上升到 105 时,可以增加额外的 0.1%风险。为了说明这个机制,想象一下在只有两个档位(一档和五档)的车里带某人去约会。一旦你在一档直线行驶了一段时间,你就会换到五档,可能正好是下一个弯道的时候。

如果你想提高传递基因的机会,你和你的旅行伴侣可能会喜欢更*稳的行驶。简化的凸形定位算法中的振荡器就像是自动变速箱,它将确保从最小风险*稳舒适地过渡到最大风险。

经典股票曲线交易的主要问题是滞后。避免滞后的最简单方法是从峰值而不是从底部测量回撤。基本上,你将始终以最佳速度驾驶投资组合,但只在必要时减速。

方法如下:

  • 回撤容忍度:这是资本的最小部分,如果有X%的回撤,将会被使用。例如,一家著名的对冲基金在-5%的回撤容忍度之后,管理资产将减少 50%。分配资本的一部分在合成上就像是承担了更少的风险。系统要么承担更少的风险,要么投入更少的资金。结果在合成上是一样的。

  • 回撤振荡器:使用上述容忍度重新调整回撤。建立一个跟踪当前资产曲线与其峰值和尾部跌幅的振荡器……

  • 振荡器形状:凹形或凸形。把这个小巧的复杂宝石看作是汽车中自动变速器的等效物。经典股票曲线交易中存在固有的滞后。风险降低得不够快以减少冲击。相反,在回撤之后恢复速度较慢。

凹性和凸性都加速了下降和恢复,如下面的理论示例所示:

def concave(ddr, floor):
    '''
    For demo purpose only
    '''
    if floor == 0:
        concave = ddr
    else:
        concave = ddr ** (floor)
    return concave

# obtuse 
def convex(ddr, floor):
    '''
    obtuse = 1 - acute
    '''
    if floor == 0:
        convex = ddr
    else:
        convex = ddr ** (1/floor)
    return convex

# instantiate minimum Kapital 
floor = np.arange(0,1,0.125)
# print('floor', floor)

x = -np.linspace(0, 1, 100)

fig, ax = plt.subplots()
for i,f in enumerate(floor):
    y = concave(ddr=-x, floor=f)
    current_label = f' concave f = {f:.3}'
    ax.plot(x, y, linewidth=2, alpha=0.6, label=current_label)

ax.legend()
plt.ylabel('Concave Oscillator')
plt.xlabel('Equity Curve From Trailing Trough To Peak')
ax.set_ylim(ax.get_ylim()[::-1])
plt.show()

fig, ax = plt.subplots()
for i,f in enumerate(floor):
    y = convex(ddr=-x, floor=f)
    current_label = f' convex f = {f*10:.3}'
    ax.plot(x, y, linewidth=2, alpha=0.6, label=current_label)
ax.legend()

plt.ylabel('Convex Oscillator')
plt.xlabel('Equity Curve From Trailing Trough To Peak')
ax.set_ylim(ax.get_ylim()[::-1])
plt.figure(figsize=(20,8))
plt.show() 

此函数的输出是如下图所示的图形:

图 8.2:各个水*上的凹形振荡器

图 8.3:各个水*上的凸形振荡器

凸形位于对角线上方,凹形位于对角线下方。这条 45 度线是线性下降线。当与回撤容忍度结合时,它已经足够好了。当最小风险与最大风险之比较高时,凹性和凸性真的很有帮助。例如,如果最小风险是-0.25%,最大风险是-1%,那么凹性或凸性都将有助于传输。

接下来,让我们来说明这个振荡器在实践中是如何工作的。我们将通过下载德国 DAX 指数的调整收盘价来模拟一个资产曲线,使用 Yahoo Finance。接下来,我们实例化一个数据框架,并使用cummax()方法计算峰值资产。然后我们计算从峰值开始的回撤。

dd_tolerance是我们愿意在撞击风险之前容忍的回撤容忍度。为了保险起见,我们绘制了数据框。这给了我们一个很好的起始基础:

ticker = '^GDAXI'
dd_tolerance = -0.1

equity = pd.DataFrame()
start = '2017-12-31'
end = None
equity['equity'] =  yf.download(tickers= ticker,start= start, end = end,
                        interval = "1d",group_by = 'column',
                        auto_adjust = True, prepost = True,
                        treads = True, proxy = None)['Close']

equity['peak_equity'] = equity['equity'].cummax()
equity['tolerance'] = equity['peak_equity'] * (1 + dd_tolerance )
equity['drawdown'] = equity['equity'] /equity['equity'].cummax() -1

equity.plot(style = ['k','g-.','r-.','m:'] ,
            secondary_y=['drawdown'], figsize=(20,8),grid=True)
equity.columns 

你应该观察类似以下的图表:

图 8.4:权益曲线,峰值权益,回撤和回撤容忍度带

一个观察立即显现出来。如果这个权益曲线与你的真实权益曲线有任何接*,那么坚持在周日烧烤,向容易受骗的游客写新闻简报,或者教给富家子弟有效市场假说EMH)。这张图表尖叫着冒牌者综合征。

图表顶部的虚线是回撤。它绘制在次要y轴上。图表上下两条虚线分别是峰值权益和回撤容忍度。如果权益曲线跌破下线,那么风险应该被降低。正如下方虚线所示,权益曲线在回撤曲线下方花费了相当长的时间。因此我们预计一段时间内交易的风险会处于最低水*。

接下来,我们将计算沿着这条权益曲线我们应该承担多少风险。根据前面的理论讨论,风险在最小值和最大值之间波动。下一个小函数对于有经验的交易者来说是最好的安眠药。它的价值是这本书的多倍:

def risk_appetite(eqty, tolerance, mn, mx, span, shape):
    '''
    eqty: equity curve series
    tolerance: tolerance for drawdown (<0)
    mn: min risk
    mx: max risk
    span: exponential moving average to smoothe the risk_appetite
    shape: convex (>45 deg diagonal) = 1, concave (<diagonal) = -1, else: simple risk_appetite
    '''
    # drawdown rebased
    eqty = pd.Series(eqty)
    watermark = eqty.expanding().max() 
    # all-time-high peak equity
    drawdown = eqty / watermark - 1 
    # drawdown from peak
    ddr = 1 - np.minimum(drawdown / tolerance,1) 
    # drawdown rebased to tolerance from 0 to 1
    avg_ddr = ddr.ewm(span = span).mean() 
    # span rebased drawdown

    # Shape of the curve
    if shape == 1: # 
        _power = mx/mn # convex 
    elif shape == -1 :
        _power = mn/mx # concave
    else:
        _power = 1 # raw, straight line
    ddr_power = avg_ddr ** _power # ddr 

    # mn + adjusted delta
    risk_appetite = mn + (mx - mn) * ddr_power 

    return risk_appetite 

这是它的工作原理:

  1. eqty序列计算峰值权益,金融克里奥尔语中的水印。

  2. 使用回撤容忍度计算回撤和调整后的回撤。使用指数移动*均值*滑*均调整后的回撤。

  3. 选择曲线的形状:凹(-1),凸(1),或线性(其他)。

  4. 计算风险偏好振荡器。

接下来,我们通过权益曲线运行几行代码来计算整个周期内的风险预算。风险预算是我们愿意承担的权益的比例。例如,如果我们使用常量风险资本为-0.50%,那么它将是当前权益乘以-0.50%。

在下面的示例中,我们使用三个风险水*:最小为-0.25,最大为-0.75%,*均为-0.50%。对于练习的目的,*均风险是恒定的风险资本。下面是源代码:

eqty= equity['equity']
tolerance= dd_tolerance
mn= -0.0025 
mx= -0.0075 
avg = (mn + mx)/2
span= 5 
shape = 1
equity['constant_risk'] = -equity['equity'] * avg
equity['convex_risk'] = -risk_appetite(eqty, tolerance, mn, mx, span, shape=1) * equity['peak_equity'] 
equity['concave_risk'] = -risk_appetite(eqty, tolerance, mn, mx, span, shape=-1) * equity['peak_equity'] 

equity[['equity', 'peak_equity', 'tolerance',
        'constant_risk','convex_risk','concave_risk']].plot(figsize= (20,8),grid=True,
    secondary_y=['constant_risk','convex_risk','concave_risk'],
    style= ['k','g-.','r-.','b:','y-.', 'orange'])

equity[['drawdown','constant_risk','convex_risk','concave_risk']].plot(grid=True,
    secondary_y=['drawdown'],style= ['m--','b:','y-.', 'orange'], figsize= (20,8) ) 

注意,常量风险是乘以当前权益水*,而凹形和凸形都使用峰值权益。最后两者在计算中包含了回撤。

我们有与之前相同的权益曲线以及峰值和容忍度。然后,我们有两个风险预算图表。

图 8.5:权益曲线,峰值和回撤容忍度。凹形,凸形和恒定风险资本

凹线,实线,是三者中最具响应性的风险预算。它反映了资产曲线。凸线,虚线,是三者中最保守的。它会在最小风险下停留更长时间,但在持续的上涨趋势中会做出积极反应。恒定风险,点线,几乎不波动。虽然表面上看起来可能不像一件坏事,但它可能会对资产曲线造成严重损害。例如,中间部分往往更加显著。在一天结束时,选择不在事情出错时减少风险也是一种风险管理决策,只是不是一个好的决定。

下一个图表绘制了风险预算以及回撤。

图 8.6:回撤,凹,凸和恒定风险资产

上面的图表显示了振荡器对回撤的响应。相比之下,恒定的风险资产看起来迟钝而不精细。当中间部分的回撤加深和恶化时,恒定风险变得太冒险了。相反,当回撤较小时,恒定风险未能利用这些机会。与等权重或马丁格尔相比,这种头寸大小算法并不差。它只是不够精细。

现在,你应该选择凹线还是凸线?最优的数学答案可能不是适合你的答案。波尔多、勃艮第还是北罗纳的葡萄酒更好?对于那些自从人类诞生以来就一直困扰人类的深刻存在问题,没有对错答案。

比较头寸大小算法

让我们举个例子进一步说明这个原则。让我们使用完全相同的信号和起始资本。然后,让我们使用各种头寸大小算法。我们为每种头寸大小算法计算资产曲线。目标是看看头寸大小如何影响收益。

为了演示目的,我们将重用我们的软银绝对法与乌龟入门,以及我们从第五章制度定义中的regime_breakout()函数。再次强调,请不要在家里这样做,因为这太简单了,无法用于专业投资产品:

def regime_breakout(df,_h,_l,window):
    hl =  np.where(df[_h] == df[_h].rolling(window).max(),1,
                                np.where(df[_l] == df[_l].rolling(window).min(), -1,np.nan))
    roll_hl = pd.Series(index= df.index, data= hl).fillna(method= 'ffill')
    return roll_hl

def turtle_trader(df, _h, _l, slow, fast):
#### removed for brevity: check GitHub repo for full code ####
    return turtle
# CHAPTER 8

ticker = '9984.T' # Softbank
start = '2017-12-31'
end = None
df =  round(yf.download(tickers= ticker,start= start, end = end, 
                        interval = "1d",group_by = 'column',auto_adjust = True, 
                              prepost = True, treads = True, proxy = None),0)

ccy_ticker = 'USDJPY=X'
ccy_name = 'JPY'
ccy_df = np.nan

df[ccy_name] =  round(yf.download(tickers= ccy_ticker,start= start, end = end, 
                        interval = "1d",group_by = 'column',auto_adjust = True, 
                              prepost = True, treads = True, proxy = None)['Close'],2)
df[ccy_name] = df[ccy_name].fillna(method='ffill')
slow = 50
fast = 20 
df['tt'] = turtle_trader(df, _h= 'High', _l= 'Low', slow= slow,fast= fast)
df['tt_chg1D'] = df['Close'].diff() * df['tt'].shift()
df['tt_chg1D_fx'] = df['Close'].diff() * df['tt'].shift() / df[ccy_name]

df['tt_log_returns'] = np.log(df['Close'] / df['Close'].shift()) * df['tt'].shift()
df['tt_cumul_returns'] = df['tt_log_returns'].cumsum().apply(np.exp) - 1 

df['stop_loss'] = np.where(df['tt'] == 1, df['Low'].rolling(fast).min(),
                    np.where(df['tt'] == -1, df['High'].rolling(fast).max(),np.nan))# / df[ccy_name]
df['tt_PL_cum'] = df['tt_chg1D'].cumsum()
df['tt_PL_cum_fx'] = df['tt_chg1D_fx'].cumsum()

df[['Close','stop_loss','tt','tt_cumul_returns']].plot(secondary_y=['tt','tt_cumul_returns'],
                                  figsize=(20,10),style= ['k','r--','b:','b'],
                       title= str(ticker)+' Close Price, Turtle L/S entries')

df[['tt_chg1D','tt_chg1D_fx']].plot(secondary_y=['tt_chg1D_fx'],
                                  figsize=(20,10),style= ['b','c'],
                                 title= str(ticker) +' Daily P&L Local & USD')

df[['tt_PL_cum','tt_PL_cum_fx']].plot(secondary_y=['tt_PL_cum_fx'],
                                  figsize=(20,10),style= ['b','c'],
                                 title= str(ticker) +' Cumulative P&L Local & USD') 

这是我们经常使用的示例。通常,今天我们在收盘时有一个信号。明天我们将进入或退出。使用位移方法,进入和退出的时间比信号滞后一天。我们计算累积收益(tt_cumul_returns)和每日盈亏(tt_chg1D)。这给我们以下图表:

图 8.7:软银收盘价,多头/空头头寸,使用绝对系列的乌龟入门

上面的图表总结了策略。用黑色实线表示收盘价,紧随其后的是红色虚线的止损线。然后,我们有+/-1 的点线表示多头/空头头寸。最后,实线蓝色代表累积收益。

图 8.8:策略每日盈亏,以本地货币和美元计价

上图表示本地货币和调整为美元的每日盈亏。*直线表示没有活跃头寸时。

图 8.9:本地货币和美元中的策略累积盈亏

上图表示本地货币和美元中的累积盈亏。我们在同一工具上使用相同的策略,没有额外的特性,如基准或流动性调整。一切都严格相同。唯一的区别是仓位调整算法。

让我们定义几种标准的仓位调整算法。等权重在此处未定义,因为它是一个数值常量,相当于资产的 3%。与使用更多奇特的仓位调整算法相比,我们选择保持简单。我们将使用两种最流行的仓位调整算法:等权重和风险等值。接着我们将把它们与这个凹凸不*的风险等值进行比较。后两者是新加入的。首先,风险等值的源代码如下:

def eqty_risk_shares(px,sl,eqty,risk,fx,lot):
    r = sl - px
    if fx > 0:
        budget = eqty * risk * fx
    else:
        budget = eqty * risk
    shares = round(budget // (r *lot) * lot,0)
#     print(r,budget,round(budget/r,0))
    return shares

px = 2000
sl = 2222

eqty = 100000
risk = -0.005
fx = 110
lot = 100

eqty_risk_shares(px,sl,eqty,risk,fx,lot) 

这将产生以下输出:

-300.0 

上述函数返回使用价格(px)、以本地货币计价的止损(sl)、资产(eqty)、risk、基金货币中的fx,基金运作的货币以及lot大小的股票数量。在上面的示例中,这将返回 -300 股。

接下来,我们用 4 种仓位调整算法运行模拟:等权重、常数、凹凸风险等值:

starting_capital = 1000000
lot = 100
mn = -0.0025
mx = -0.0075
avg = (mn + mx) / 2
tolerance= -0.1
equal_weight = 0.05
shs_fxd = shs_ccv = shs_cvx = shs_eql = 0
df.loc[df.index[0],'constant'] = df.loc[df.index[0],'concave'] = starting_capital
df.loc[df.index[0],'convex'] = df.loc[df.index[0],'equal_weight'] = starting_capital

for i in range(1,len(df)):
    df['equal_weight'].iat[i] = df['equal_weight'].iat[i-1] + df['tt_chg1D_fx'][i] * shs_eql
    df['constant'].iat[i] = df['constant'].iat[i-1] + df['tt_chg1D_fx'][i] * shs_fxd
    df['concave'].iat[i] = df['concave'].iat[i-1] + df['tt_chg1D_fx'][i] * shs_ccv
    df['convex'].iat[i] = df['convex'].iat[i-1] + df['tt_chg1D_fx'][i] * shs_cvx

    ccv = risk_appetite(eqty= df['concave'][:i], tolerance=tolerance, 
                        mn= mn, mx=mx, span=5, shape=-1)
    cvx = risk_appetite(eqty= df['convex'][:i], tolerance=tolerance, 
                        mn= mn, mx=mx, span=5, shape=1)

    if (df['tt'][i-1] ==0) & (df['tt'][i] !=0):
        px = df['Close'][i]
        sl = df['stop_loss'][i]
        fx  = df[ccy_name][i]
        shs_eql = (df['equal_weight'].iat[i]  * equal_weight  *fx//(px * lot)) * lot
        if px != sl:
            shs_fxd = eqty_risk_shares(px,sl,eqty= df['constant'].iat[i],
                                        risk= avg,fx=fx,lot=100)
            shs_ccv = eqty_risk_shares(px,sl,eqty= df['concave'].iat[i],
                                            risk= ccv[-1],fx=fx,lot=100)
            shs_cvx = eqty_risk_shares(px,sl,eqty= df['convex'].iat[i],
                                            risk= cvx[-1],fx=fx,lot=100)

df[['constant','concave','convex','equal_weight', 'tt_PL_cum_fx']].plot(figsize = (20,10), grid=True,
    style=['y.-','m--','g-.','b:', 'b'],secondary_y='tt_PL_cum_fx',
title= 'cumulative P&L, concave, convex, constant equity at risk, equal weight ') 

该代码的执行步骤如下:

  1. 首先,我们实例化参数,如起始资本、货币、最小和最大风险、回撤容忍度和等权重。

  2. 我们初始化每个posSizer的股票数量。我们也初始化每个posSizer的起始资本。

  3. 我们循环遍历每个柱状图,通过将前一个值加上当前股票数量乘以每日盈利来重新计算每个资产曲线。

  4. 我们在每个柱状图重新计算凹凸风险震荡器。

  5. 如果有入场信号,我们计算每个posSizer的股票数量。//运算符是取模运算符。它返回除法的四舍五入整数。这是一个快速计算整数的妙招。注意凹凸之间唯一的区别是符号:–1+1

然后我们打印资产曲线,完成。顶部的虚线是凹凸的。下面,虚点线是凸的,接着是常数。次要垂直轴表示权重调整前的累积盈亏:

图 8.10:使用各种仓位调整算法的资产曲线

让我们在这里简要回顾一下。我们使用相同的策略,其中根据货币调整的累积回报由上面的实线蓝线表示。唯一的区别是资金管理。在远离地球的一个遥远星系中,行业标准的等权重排名靠后。在这种情况下,我们使用 5%的权益,这是一种经验丰富的机构经理人会称之为“高信心”的赌注大小。一个很好的倒数第二是恒定风险权益。它要么是第一档,要么是第五档。凹形风险权益令人惊讶地排在第一位。凸形在波动市场中的响应性更好,而凹形在趋势市场中表现良好。

重要的启示是,赚钱是在资金管理模块中完成的。你下注的聪明程度决定了你赚多少钱。最佳的投资回报不是来自于拜访更多公司、打更多电话、阅读更多分析师报告或者研究更多图表分析。最佳的投资回报来自于完善资金管理模块。

优化你的风险预算

在资金管理算法中稍加精细,会产生很大的作用。这导致我们在风险预算方面进行一些小的改进,如摊销和误报。

风险摊销

"金字塔加仓的指导出现在一张美元钞票上。在上升过程中越来越小心地增加。在顶端保持警惕。"

– 埃德·赛科塔

空头方面有一套独特的挑战。成功的空头头寸会缩小。头寸需要定期加码。在现有头寸上增加头寸被称为金字塔加仓。金字塔加仓是一项微妙的业务。

一方面,趋势成熟。随着时间的流逝,逆转的概率增加。因此,每增加一个持仓,每笔交易的风险都应该降低。另一方面,新闻流的恶化验证了最初的看跌立场。市场参与者往往会诱使他们大幅增加投注。根据我的个人经验,每当市场评论员开始赞同我的立场,我开始感到聪明时,都会不可避免地出现一场讨厌的熊市反弹。

缓解进入成熟趋势的风险的一个简单方法是为每个新头寸摊销风险。以下代码片段是给那些通常增加头寸的市场参与者的建议。随着时间的流逝,随着风险的增加,应该减少头寸。

def pyramid(position, root=2):
    '''
    position is the number of positions
    power is root n. 
    Conservative = 1, aggressive = position, default = 2
    '''
    return 1 / (1+position) ** (1/root)
def amortized_weight(raw_weight, amortization):
    '''
    raw_weight is the initial position size
    amortization is pyramid(position,root=2)
    '''
    return raw_weight * amortization
weight = 0.05
position = np.arange(1,4)
print('position', position)
print('linear',pyramid(position, root=1)* weight)
print('square root',pyramid(position, root=2)* weight)
print('position n',pyramid(position, root=position)* weight) 

在公式之后是一个数值示例。我们从 5%的头寸大小(weight)开始。我们使用np.arange方法重新进入三次。然后,我们使用各种摊销计算了对原始头寸的 3 次增加的建议权重大小,得到以下结果:

position [1 2 3]
linear [0.025      0.01666667 0.0125    ]
square root [0.03535534 0.02886751 0.025     ]
position n [0.025      0.02886751 0.03149803] 

linear 代表无权力。在第一个额外的分段中,仓位大小为原始仓位(0.025)的 ,第二个分段为 ,以此类推。使用 square root 暗示了第一个额外分段的大小为原始仓位(0.3535)的 倍,第二个仓位的大小为原始仓位的 倍。 position n 暗示了第一个额外分段的大小为原始仓位的 倍,与线性分段相同,第二个分段的大小为原始仓位的 倍,与*方根摊销相同,依此类推。

*方根可能是一个不错的折中方案。它使市场参与者能够承担相当大的风险而不至于面临破产的风险。再次强调,卖空是一个仓位规模的练习,而不是一场股票挑选比赛。小仓位没有贡献。大仓位是有风险的。有一个最佳数量,对此我们内心的白痴完全不会有任何反应。再一次,市场参与者可以选择保守还是积极。有老交易员和大胆交易员。老而大胆的交易员极少。

假阳性

并非所有交易第一次就奏效。有时,一只股票需要两三次尝试才能最终按预期行事。这对股权曲线造成了损失。市场参与者经常受到诱惑,对其信号引擎进行全面改革和调整,以减少假阳性的频率。尽管对导致不良交易的盲点进行改进可能有一些价值,但毫无疑问,接受假阳性也是旅程的一部分。无法消除随机性。

我们通常很擅长处理生活中其他领域的失望。当某事不起作用时,我们会投入更少的时间和精力。同样,解决方案可能不是对信号引擎的又一次调整。当股票拒绝按预期行事时,继续尝试,只是投资更少。这归结为上文定义的风险摊销函数。为每次失败的尝试分摊风险。

订单优先级和交易拒绝

在某个时候,你会有更多的信号而没有足够的资金去投资。你将不得不做出艰难的选择和优先选择信号。最简单的订单优先级算法是大小:尺寸越大,风险/回报越高。按绝对尺寸降序排列所有头寸。并不是因为你坐在办公桌前,市场开放,你就应该毫无节制地交易。选择不交易是一个重要的交易决定。

交易拒绝是做空者武器库中的重要工具。在多头方面,小头寸可以发展成强大的持仓。比尔·盖茨在 1997 年 8 月以每股 12 美元的价格购买了 AAPL 股票。另一方面,在做空方面,一个-0.50%的头寸下跌-10%只会贡献-0.05%。这几乎不是吸引投资者的回报方式。当头寸太小而无法造成伤害时,它们也太小而无法做出贡献。

可能导致持有小头寸的原因可能是:

  • 表现出现了“软裁判”

  • 这种特定策略现在不受欢迎了

  • 这一方面(多头/空头)不起作用

  • 仪器本身的胜率令人沮丧

  • 已经有几个入场

无论原因是什么,这都不是一个明显的机会,所以你希望保持你的筹码清醒。

头寸大小的博弈论

“你可以通过观察学到很多东西。”

– 尤吉·贝拉,伟大的美国哲学家

最*的计算技术进步鼓励市场参与者尝试运用博弈论,尤其是在股票选择方面。博弈论也非常适合用于头寸大小的确定。使用博弈论进行入场的区别在于,结果是二进制的:要么入场,要么不入场。在那里几乎没有学习的可能性,因为没有人会统计未做出的选择。除非你是一个可怕的跟踪者,你不会去关注你没有娶的前任。

股票曲线侵蚀的主要原因之一是虚假阳性。一些股票可能会有两三次虚假的起步,然后才真正起飞。然后,需要时间来偿还这些虚假的起步。与此同时,一些股票在第一次尝试时表现良好。在被称为股票市场的概率游戏中,没有办法提前知道哪个会是哪个。奖励那些表现良好的股票,并为那些表现不佳的股票摊销风险是一种简单的启发式。这就是博弈论和一个可爱的小故事发挥作用的地方。

这是我们用来奖励表现良好的股票的算法背后的故事。有一次我早早地到校接孩子。我女儿正在玩一个我们小时候都玩过的游戏,所以我就坐在那里看着。有趣的是,她最终赢了,并不是因为她试图预测什么,而是因为她在每一轮后都系统地做出反应。她模仿了每个参与者的行为:对那些对她友好的人友好,反之亦然,以牙还牙。这让我想到了一个简单的博弈论启发式。

快进几天在谷歌上的研究,结果表明以牙还牙的启发式在博弈论算法比赛中一再获得第一。不用说,这个博弈论模块很快就被引入我们的头寸大小方法中,用我女儿的名字命名,“Alizee”(发音为Alizay,法语中的trade winds)。以牙还牙是一个可靠的算法。惩罚不良行为,奖励良好行为。

总结

每个人都想挑选下一个 [插入热门股票代码...]。选股票很性感。然而,如果你选择进入市场赚钱,那么就要成为乏味艺术的学生。赚钱在于资金管理模块。在本章中,我们揭示了一个小功能,将风险设置委托给市场,并将持续改变经验丰富的市场参与者的睡眠质量。

接下来,我们将探讨风险。在空头方面,市场不合作。市场达尔文主义规定,幸存的空头卖方展示了卓越的风险管理能力。

第九章:风险是一个数字

“事实固执,但统计数据更易变。”

– 马克·吐温

归根结底,无论你交易美国股票、猪肚或与你的另一半交换的色彩语言,你只交易一件事:风险。学者们以开发复杂抽象指标并赋予其花哨名称来建立自己的职业。指标越深奥,他们就越有可能在某处获得终身教职。通过数学恐吓来证明是获得舒适的学术终身教职的简单途径。不幸的是,这些指标忽略了不懂行的客户在忍受令人绞痛的回撤时的体验。当市场参与者和投资者无法将抽象数字与管理投资组合的现实相 reconcil 时,他们会回到故事中。

在本章中,我们将介绍三个指标:坚韧指数、常识比率和增益期望的 t-统计量。我们的目标是揭示风险的神秘面纱,将其还原为每个人都能直观理解的东西。

我们将涵盖以下主题:

  • 导入库

  • 解读风险

  • 夏普比率:错误问题的正确数学答案

  • 坚韧指数

  • 常识比率

  • 范·塞普的 SQN

  • 鲁棒性分数

您可以通过以下链接访问本章节所有图片的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。您还可以通过本书的 GitHub 仓库访问本章节的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

在本章和本书的其余部分,我们将使用pandasnumpyyfinancematplotlib库。因此,请记得先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt 

解读风险

在空头市场,市场不配合。市场达尔文主义规定,卖空者成为杰出的风险管理者。在接下来的几节中,我们将探讨三个被极大低估的风险指标及其源代码。使用其中任何一个或全部校准风险,你可能会有长期的抗争机会。当被问及风险时,市场参与者通常会做两件事之一。

第一个方法是推出一系列指标。他们从夏普比率开始,加上一些跟踪误差的度量,用索汀诺调味,一勺特雷诺尔,一滴詹森阿尔法使其看起来不错,最后用信息比率润色,就可以提供给一群假装喜欢数字“高级烹饪”的客户了。指标的不加区分地繁殖告诉我们一件事:我们天生无法理解风险。

市场参与者的第二件事是陷入论文模式。他们讲述联邦储备系统、量化宽松、利率、技术扰动(新潮流的新同义词)等故事,[在此插入一长串警报性新闻流的清单…]。

在金融领域的俚语中,对于一个谁也无法控制的未来的所有恐惧的总和被称为忧虑之墙

风险不是所有恐惧的总和。风险不是一个故事。风险是一个数字。在微观层面上,它是你在单笔交易上能承受的损失量。在投资组合层面上,它是你能承受的全部回撤量,仍然能够赢得胜利。在专业层面上,它是你能够在某人不拘礼仪地拔掉插头之前失去的金额、频率和时间长度。在生活方式层面上,它是你可以在跳到下一个商店之前多久一次数学教给厌烦的高中生的频率。

没有人能预测这个世界会发生什么,但每个市场参与者都可以控制他们的投资组合对冲击的脆弱性。在 第一章股票市场游戏 中,我们考虑了有限与无限游戏。无限游戏的目标是保持在游戏中。如果你想玩无限游戏,那么你就需要专注于那些毫不妥协地评估你的生存能力,并让你能够活下去进行下一轮交易的指标。因此,衡量健壮性的逻辑方式就是在方程中的某个地方包含回撤。

Sharpe 比率:错误问题的正确数学答案

Sharpe 比率是行业生活中如此复杂的一部分,以至于一个*凡的问候,比如“你好吗?”很容易就能被换成“你的 Sharpe 指数如何?” 这个比率试图回答的问题在概念上很简单:对于每个波动单位,你能获得多少个超过无风险资产的超额收益单位?现在,所有的问题都不是源于公式,而是源于人们赋予波动的意义。波动是坏的、有风险的还是不确定的?

这是 Sharpe 比率的数学公式,其中 Rp 等于资产收益,而 Rf 等于无风险收益:

这个比率考虑了超过无风险资产的年化*均超额收益与这些收益的标准偏差之比。标准偏差衡量了与中位收益的方差。收益越波动,标准偏差越高,比率就越低(反之亦然)。超过无风险资产的超额收益是一个简单的测试:对于每增加一个波动单位,你是否更适合将资金放在特定的经理那里,还是将其安全地放在国债或货币市场基金中?

即使天才威廉·夏普也对他创造的并且现在已经成为默认行业标准的衡量指标——夏普比率——提出了批评。这个指标达到了它的目的。它有两件事情做得非常好:

  1. 跨资产统一度量: 现在普遍认为,α 生成中最关键的组成部分是资产配置。困难在于跨资产类别有一个统一的风险调整后的 α 度量。这就是夏普比率发挥作用的地方。它可以在固定收益、股票、商品等各种资产类别中计算。

  2. 不确定性:人类大脑天生与风险联系在一起。它触发杏仁核并激活战斗、逃跑或冻结的反应。

现在,夏普比率是在 1966 年发明的。它是在革命时代的革命性发明:埃尔·切·格瓦拉和菲德尔·卡斯特罗仍在古巴与巴蒂斯塔作战。正如先驱威廉·夏普本人所说的,当计算能力仍然有限时,这是一个好东西。但从那时起,时代已经改变了。医生已经停止给孕妇开处方香烟,塑料已经成为主导的海洋物种,比送人上月球的计算机更强大的计算机现在可以装在每个人的口袋里。

首先,让我们以我们最喜欢的 乌龟入门 策略为例,并重用regime_breakout()turtle_trader()函数。我们将在滚动和累积系列上计算风险指标。这个策略是在绝对系列上运行的。这里纯粹是为了教育目的。

def regime_breakout(df,_h,_l,window):
    hl =  np.where(df[_h] == df[_h].rolling(window).max(),1,
                                np.where(df[_l] == df[_l].rolling(window).min(), -1,np.nan))
    roll_hl = pd.Series(index= df.index, data= hl).fillna(method= 'ffill')
    return roll_hl
def turtle_trader(df, _h, _l, slow, fast):
    _slow = regime_breakout(df,_h,_l,window = slow)
    _fast = regime_breakout(df,_h,_l,window = fast)
    turtle = pd. Series(index= df.index, 
                        data = np.where(_slow == 1,np.where(_fast == 1,1,0), 
                                np.where(_slow == -1, np.where(_fast ==-1,-1,0),0)))
    return turtle
ticker = '9984.T' # Softbank
start = '2017-12-31'
end = None
df =  round(yf.download(tickers= ticker,start= start, end = end, 
       interval = "1d",group_by = 'column',auto_adjust = True, 
prepost = True, treads = True, proxy = None),0)
slow = 50
fast = 20 
#### removed for brevity: check GitHub page for full code ####
df[['Close','stop_loss','tt','tt_cumul']].plot(secondary_y=['tt','tt_cumul'],
                                  figsize=(20,8),style= ['k','r--','b:','b'],
                       title= str(ticker)+' Close Price, Turtle L/S entries, cumulative returns') 

使用对数收益而不是算术收益。它们更容易处理。累积收益是每日收益的总和,对其应用np.exp方法。

图 9.1:Softbank 乌龟入门,仓位和回报

这也是我们之前看过的一张图。它显示了 Softbank 的收盘价,带有一个在收盘价之上或之下的跟踪止损。它显示了多头和空头仓位以及累积回报。现在我们有了一个策略,让我们在滚动和累积基础上运行风险指标。

我们将从夏普比率开始。无风险回报设置为任意的十分之一个基点。

r_f = 0.00001 # risk free returns

def rolling_sharpe(returns, r_f, window):
    # Calculating average returns in a rolling window
    avg_returns = returns.rolling(window).mean()
    # Calculating the volatility of average returns in a rolling window
    std_returns = returns.rolling(window).std(ddof=0)
    # Rolling Sharpe ratio function
    return (avg_returns - r_f) / std_returns

def expanding_sharpe(returns, r_f):
    avg_returns = returns.expanding().mean()
    std_returns = returns.expanding().std(ddof=0)
    return (avg_returns - r_f) / std_returns

window = 252 
df['sharpe_roll'] = rolling_sharpe(returns= tt_log_returns, r_f= r_f, window= window) * 252**0.5

df['sharpe'] = expanding_sharpe(returns= tt_log_returns, r_f= r_f) * 252**0.5

df[window:][['tt_cumul','sharpe_roll','sharpe'] ].plot(figsize = (20,8),style = ['b','c-.','c'],grid=True,
title = str(ticker)+' cumulative returns, Sharpe ratios: rolling & cumulative') 

代码没有什么大秘密。首先,我们计算滚动夏普,然后计算累积夏普。结果使用标准公式进行年化处理:252 个工作日的*方根。

图 9.2:Softbank 累积回报和夏普比率:滚动和累积

滚动夏普虚线比代表累积夏普的实线更具波动性和响应性。这仅仅是由于数据样本大小。

风险经常被等同于波动性。它构成了可接受的公式。在这种情况下,夏普比率似乎是风险调整后回报的完美指标。唯一的问题在于,在实践中,波动性并不是风险的衡量标准。为了证明这一点,让我们提出几个夏普比率很高的策略,它们一夜之间就遇到了冰山,还有一些夏普比率很低的策略表现出色地经受住了考验。现在,一些低波动策略非常危险。以下是一些例子:

  1. 长期资本管理公司LTCM)在他们破产前的几个月采用了相当低的波动率策略。他们进行均值回归策略交易。这些策略具有一致的低波动率回报,有利于高夏普比率。也许他们能够经受得住一个诺贝尔奖,但两个就太多了。

  2. 短期伽玛波动基金:在大萧条前,波动基金是时髦的投资工具。他们的策略包括通过出售虚值OTM)期权来收取保费。由于这些期权到期为实值的概率极低,它们产生了一致的低波动率表现。它们的夏普比率高于行业*均水*。一切都进行得很顺利,直到波动率飙升并且期权到期为实值。损失呈指数增长,积累多年的回报在几周内化为乌有。短期伽玛就像是在巨大的枪管中玩一场统计学的俄罗斯轮盘赌。在你自杀的那一天之前,什么都不会发生。在行业术语中,这被称为“在蒸汽压路机前捡便士”。

相反,一些波动性策略具有异常强大的业绩记录,尽管夏普比率糟糕。作为一个群体,像保罗·图多·琼斯、艾德·赛科塔、比尔·邓恩和威廉·埃克哈特这样的系统性趋势跟踪商品交易顾问CTAs)在过去几十年一直在阿尔法产生金字塔上居高不下。回报是不稳定的。趋势跟踪者大部分时间都在保护他们的资本,在一年中只有几次收获超额回报。

总的来说,对于其创作者应给予一切谦逊的尊重,夏普比率是错误问题的正确数学答案。波动率是衡量风险的正确标准吗?夏普比率是一种波动率调整后的回报度量。波动率不等于风险,但反映了不确定性。尽管不确定性可能会在我们的哺乳动物大脑中触发一些警报,但作为市场参与者,我们的工作描述清楚地指出:“要对不适感感到舒适。”

建立一个综合风险指标

接下来的三个指标可以说更接*风险的*似值,并且更直观。

韧性指数

“当我离开餐厅时坐在格莱斯顿旁边,我觉得他是英格兰最聪明的人。但当我坐在迪斯雷利旁边时,我离开时感到自己是英格兰最聪明的女人。”

– 温斯顿·丘吉尔的母亲,珍妮·杰罗姆

投资者常常表现出与其利益相悖的行为。他们说他们想要回报,但却对回撤做出反应。更具体地说,他们对回撤有三种反应方式:

  • 幅度:永远不要测试你的投资者的胃口

  • 频率:永远不要测试你的投资者的神经

  • 恢复期:永远不要测试你的投资者的耐心

Grit 指数可以说是整个金融宇宙中最被低估的指标之一。少数几个指标能如此优雅地捕捉到稳健性。广义上讲,它通过将绩效除以一段时间内的全部损失表面来查看下行风险。该指数具有一种数学表达方式,如此直观,以至于任何人都能可视化它。对于多么长时间地为损失的众多和巨大而苦恼的时光似乎已经是很久以前的事了。

表面的数学计算称为积分。接下来,由于这些损失显然会影响到财务和情感资本,它们应该位于分母中。

最终投资者感知的是收益。而 Grit 指数则是最终投资者最终获得的除以所有损失的痛苦。这个公式最初由彼得·G·马丁于 1987 年发明,并在他的书《The Investor's Guide to Fidelity Funds》中发表为溃疡指数。传奇交易员 Ed Seykota 将其重新利用并将其命名为塞科塔湖比率。这些都是完全相同的公式,只是名称不同。由于溃疡指数或塞科塔湖比率可能未能引起它们真正应得的关注,那么将其重新命名为 Grit 指数如何?

以下是源代码:

def rolling_grit(cumul_returns, window):
    tt_rolling_peak = cumul_returns.rolling(window).max()
    drawdown_squared = (cumul_returns - tt_rolling_peak) ** 2
    ulcer = drawdown_squared.rolling(window).sum() ** 0.5
    return cumul_returns / ulcer

def expanding_grit(cumul_returns):
    tt_peak = cumul_returns.expanding().max()
    drawdown_squared = (cumul_returns - tt_peak) ** 2
    ulcer = drawdown_squared.expanding().sum() ** 0.5
    return cumul_returns / ulcer

window = 252
df['grit_roll'] = rolling_grit(cumul_returns= df['tt_cumul'] , window = window)
df['grit'] = expanding_grit(cumul_returns= df['tt_cumul'])
df[window:][['tt_cumul','grit_roll', 'grit'] ].plot(figsize = (20,8), 
                secondary_y = 'tt_cumul',style = ['b','g-.','g'],grid=True,
    title = str(ticker) + ' cumulative returns & Grit Ratios: rolling & cumulative '+ str(window) + ' days') 

Grit 计算序列如下:

  1. 使用 rolling().max()expanding().max() 计算峰值累积收益

  2. 通过从峰值减去累积收益并对其进行*方来计算*方回撤

  3. 通过取*方回撤的*方根来计算最小二乘和

  4. 将累积收益除以溃疡指数

该代码生成以下图表:

图片

图 9.3:Softbank 累积收益和 Grit 比率:滚动和累积

让我们来看看图表的进展。在上半部分,Grit 指数反映了绩效。在下半部分,绩效跳升,但回撤的幅度和持续时间也随之增加。该指数落后于流星般的上升。该策略有效,但存在一些回撤期,因此指数**。该度量标准仅使用了对投资者真正重要的两个变量:绩效和回撤。如果将绩效视为最终目的地,那么将其除以损失面积就显示了旅程,以及道路上的所有颠簸。

在一天结束时,人类之所以无法取得伟大成就并非因为没有崇高的目标。他们放弃的原因在于旅程的艰辛。而这正是这个比率的作用。这个指数达到了与夏普比率相同的效果,同时考虑到了通往优异表现的漫长道路上的所有颠簸。它相对于夏普比率具有以下优点:

  1. 跨资产统一度量: 它在每种资产类别、每种策略、每个时间框架中均匀工作,在绝对和相对系列中均匀工作。

  2. 不确定性:这个指标专注于投资者真正关心的回撤方面:幅度、频率和恢复周期。相比之下,夏普比率将不确定性与恐惧混为一谈。它惩罚高波动性策略,而不管它们的盈利能力如何。

它比夏普比率做得更多。反向工程高夏普比率的最简单方法是减少波动性。只要波动性被压缩,即使是最温和的回报看起来也不错。微小的分母将放大任何中等的分子。难怪资金流向固定收入。回报率非常*庸,但是非常可预测。

另一方面,坚韧指数关注的是累积而不是*均收益。这是退休后银行账单底部的数字。因此,这一指标对稳定的中等稳定收入类型的容忍度较低。然而,这个指数也会惩罚投资者真正关心的唯一事情:下行波动性。退休后,养老金领取者只关注他们账户中的总金额。他们不关心*均每日收益的稳定性。稳定的日常收益对基金经理来说是一种令人愉悦的衡量标准,而不是对养老金领取者来说。当市场参与者使用夏普比率或资本资产定价模型CAPM)来配置资产时,他们会以稳定性换取回报。固定收入的夏普比率比股票高。它还有哮喘般的回报。

坚韧指标的特权在于,即使对于完全财务无知的人来说,它也会强加于他们自己。没有比生活更好的隐喻来解释这一指标了。绩效是你取得的成就。生活是你做其他计划时发生的事情,以及一路上的所有挫折。将你的成就除以障碍,你就得到了一个相当健壮的坚韧度量。在实践中,坚韧指数的健壮性意味着它可以用作策略之间的资产配置关键。

常识比率

“常识并不常见。”

–伏尔泰,自由斗士

进入杰克·施瓦格。在我的个人愿望清单上,与《市场巫师》系列作者进行一对一会议几乎就像是得到了“非常感谢”从埃尔维斯或从詹姆斯·布朗那里得到了输血。几十年前出版的他的书现在和当时一样相关。

我有幸促成施瓦格先生在东京的一次亚洲证券投资会议上发表主题演讲。所以,我们在讨论他被低估的智慧之宝,《市场的感觉与胡言乱语》。在其中,他讨论了得益于痛苦的比率,更为人所熟知的是利润比率

本质上,这是交易边缘/收益期望的分数版本。在谈话中的某个时刻,我介绍了我的自制小指标,一个两个比率的混合物,他的回答是,“嗯,这是常识。”大师已经说过了。我现在可以死了,虽然有点困惑。几个小时后回到牧场,我向老板揭示了它并解释了理由:“是啊,老兄,这是常识,”我的老板大大地阐述道。

当两个人的尊重被以对数刻度绘制时达成相同的结论……哇:常识比率CSR)诞生了。这个度量背后的原理是有两种方式失败:要么是积分,要么是被击倒。策略失败的两种方式是要么有过多的累积损失,要么是少数毁灭性打击。这回到了曾经交易的两种类型的策略:趋势跟踪或均值回归。趋势跟踪相关的风险在于聚合。均值回归相关的风险在于尾部。

两种策略具有不同的风险因素,聚合或尾部。它们需要不同的风险度量标准。CSR 的理由是提出一个统一的度量标准。回到小学时代,当我的数学技能还没有达到一个“永久性的低水*”时,有这样一个奇妙的乘法传递性概念。将这两种策略的风险度量标准最简单的结合方法是将利润与痛苦(利润)比率乘以尾部比率。以下是第六章,“交易边缘是一个数字,这是一个公式”的原始代码的复习,再加上 CSR:

def rolling_profits(returns,window):
#### removed for brevity: check GitHub repo for full code ####
def rolling_losses(returns,window):
#### removed for brevity: check GitHub repo for full code ####
def expanding_profits(returns): 
#### removed for brevity: check GitHub repo for full code ####
def expanding_losses(returns): 
#### removed for brevity: check GitHub repo for full code ####
def profit_ratio(profits, losses):    
#### removed for brevity: check GitHub repo for full code ####
def rolling_tail_ratio(cumul_returns, window, percentile,limit):
    left_tail = np.abs(cumul_returns.rolling(window).quantile(percentile))
    right_tail = cumul_returns.rolling(window).quantile(1-percentile)
    np.seterr(all='ignore')
    tail = np.maximum(np.minimum(right_tail / left_tail,limit),-limit)
    return tail

def expanding_tail_ratio(cumul_returns, percentile,limit):
    left_tail = np.abs(cumul_returns.expanding().quantile(percentile))
    right_tail = cumul_returns.expanding().quantile(1 - percentile)
    np.seterr(all='ignore')
    tail = np.maximum(np.minimum(right_tail / left_tail,limit),-limit)
    return tail

def common_sense_ratio(pr,tr):
    return pr * tr    
window = 252
df['pr_roll'] = profit_ratio(profits= rolling_profits(returns = tt_log_returns,window = window), 
                             losses= rolling_losses(returns = tt_log_returns,window = window))
df['pr'] = profit_ratio(profits= expanding_profits(returns= tt_log_returns), 
                             losses= expanding_losses(returns = tt_log_returns))

df[window:] [['tt_cumul','pr_roll','pr'] ].plot(figsize = (20,8),secondary_y= ['tt_cumul'], 
                            style = ['r','y','y:'],grid=True) 

在这里,我们计算滚动和累积比率并打印它们:

图 9.4:累积收益和常识比率:累积和滚动

利润比率是趋势跟踪策略最合适的风险度量标准。风险在于聚合,正如我们在第六章,“交易边缘是一个数字,这是一个公式”和第八章,“头寸规模:货币是在货币管理模块中赚的”中看到的。前面的图表显示了一个健康但不太出色的利润比率。换句话说,该策略在其当前的代理人(直立人的祖先)格式下似乎是有效的。

我们将以 CSR 作为结论,它是利润比率和尾部比率的乘积:

window = 252

df['tr_roll'] = rolling_tail_ratio(cumul_returns= df['tt_cumul'], 
                             window= window, percentile= 0.05,limit=5)
df['tr'] = expanding_tail_ratio(cumul_returns= df['tt_cumul'], percentile= 0.05,limit=5)

df['csr_roll'] = common_sense_ratio(pr= df['pr_roll'],tr= df['tr_roll'])
df['csr'] = common_sense_ratio(pr= df['pr'],tr= df['tr'])

df[window:] [['tt_cumul','csr_roll','csr'] ].plot(secondary_y= ['tt_cumul'],style = ['b','r-.','r'], figsize = (20,8),
    title= str(ticker)+' cumulative returns, Common Sense Ratios: cumulative &  rolling '+str(window)+ ' days') 

图表反映了相对健康的 CSR,没有隐藏的惊喜。

图 9.5:累积收益和常识比率:累积和滚动

对于趋势跟踪策略而言,会引起担忧的模式是指数值越来越重。随着策略的进展,累积损失的权重将越来越重要。对于均值回归策略而言,会引起担忧的模式是稳定的低值指数突然下降。这表明利润无法弥补损失。

CSR 指标重新评估了两种策略相关的风险。它还强烈提示了从损失中恢复以及策略的周期性的能力。以下示例演示了这个指标在实践中的运作方式。

示例 1:假设一种策略每年返回 10%。最佳月份的 95^(th) 百分位点为 +0.6%,而最差月份的 5^(th) 百分位点为 -2%。可以计算出以下值:

  • 收益与痛苦比 = 1.1

  • 尾比 = |0.6%/-2%| = 0.3

  • CSR = 1.1 * 0.3 = 0.33

CSR 低于 1 表明该策略容易受到冲击。比率低于 0.5 意味着该策略可能无法从严重冲击中恢复。CSR 尤其有效地识别了均值回归策略中的隐藏风险。均值回归策略给人以稳定和健壮的外观。利润以节拍器般的规律性滚入。然而,不可预测的左尾事件会扰乱这种稳定性。

这种策略似乎会产生稳定的 +10% 每年的利润,但 0.3 的尾比表明,它需要三倍的时间来从事故中恢复。唯一重要的问题是:投资者是否有足够的耐心,还是会削减损失并寻找其他投资渠道?这个问题的答案可能可以在 2007 年量化交易员的覆灭故事中找到。那些策略多年来表现良好,但当它们经历意外的回撤时,相对于它们的月*均回报来说是相对较大的,投资者会赎回。

我们将考虑以前策略的一些失败以及一些需要避免的陷阱,在 第十章优化投资领域 中。

示例 2:假设一种策略在完整周期内落后于基准 2%(GPR = 0.98)。假设赢家是输家的三倍大,或者尾比为 3。再次计算出先前定义的函数的必要值:

  • 收益与痛苦比 = 0.98

  • 尾比 = 3

  • CSR = 0.98 * 3 = 2.94

由于相对的收益与痛苦比为 0.98,你可能会想,“为什么要投资一个随着时间推移而亏损的投资渠道呢?”欢迎来到你的*均共同基金。随着时间的推移,费用会侵蚀绩效,导致共同基金表现不佳。然而,绩效是周期性的。有时,经理们表现出色。CSR 是一种简单的入市和更重要的是退出市场的时机。高 CSR 结合次优的利润/收益与痛苦比是强烈季节性的证据。这些产品在某些时候运作得非常好,但在长期内失败。在 第五章制度定义 中,我们看到了几种制度定义方法,这些方法应该有助于识别季节性。

范·萨普的 SQN

这个统计量是由范·萨普博士重新带回人们的视线。系统质量数 SQN® 是对久负盛名的 t-统计量的精彩解释。它具备衡量稳健性所需的所有要素。首先,只有当策略具备交易优势时才是可行的。直到盈利预期变为正之前,一切都不会发生。

其次,它包含交易频率。挣钱是一回事,按时交易是另一回事。策略能够在维持正盈利预期的同时进行更多交易,收益复利速度越快。时间是立即跳入脑海的变量。

市场参与者应尽可能降低时间框架,只要他们能够维持正盈利预期。例如,一个在日线和 4 小时线上可行的策略将在较低的时间框架上生成更多信号。此外,较短的时间框架意味着更紧密的止损和更大的仓位,但也意味着信号更嘈杂。

第三,结果被归一化。它们以标准偏差表示,这在这种情况下意味着交易优势的波动性。当涉及到收益时,每个人都喜欢高峰,但没有人喜欢低谷。最后但并非最不重要的,代码实现起来非常简单:

def expectancy(win_rate,avg_win,avg_loss):  
    # win% * avg_win% - loss% * abs(avg_loss%) 
    return win_rate * avg_win + (1-win_rate) * avg_loss 
def t_stat(signal_count, trading_edge): 
    sqn = (signal_count ** 0.5) * trading_edge / trading_edge.std(ddof=0) 
    return sqn 
# Trade Count
df['trades'] = df.loc[(df['tt'].diff() !=0) & (pd.notnull(df['tt'])),'tt'].abs().cumsum()
signal_count = df['trades'].fillna(method='ffill')
signal_roll = signal_count.diff(window)
# Rolling t_stat
#### removed for brevity: check GitHub repo for full code ####
# Cumulative t-stat
#### removed for brevity: check GitHub repo for full code ####
df[window:][['tt_cumul','sqn','sqn_roll'] ].plot(figsize = (20,8),
                secondary_y= ['tt_cumul'], grid= True,style = ['b','y','y-.'], 
                 title= str(ticker)+' Cumulative Returns and SQN: cumulative & rolling'+ str(window)+' days') 

代码的工作方式如下:

  1. 需要将信号数量与制度分开。.diff() 识别制度变化的时候:从 0 到 1,反之亦然。notnull() 方法确保信号在进入时被计算一次。从那里开始,abs() 将所有交易计算为一个。通过 cumsum() 进行累积和。然后,fillna 方法向前填充所有缺失的值。.diff(window) 应用于交易列,返回滚动交易数量。

  2. 接下来,我们计算滚动系列。复制每日收益并将亏损日标记为 N/A。这样就留下了正收益。我们计算移动*均计数并将其除以窗口。类似地,我们计算滚动利润和损失,并将它们除以窗口。

  3. 累计计算的方法略有不同。使用扩展方法计算收益的累积计数。以相同的方式计算正收益的累积计数。然后,计算胜率、*均获胜和损失。

  4. 我们在 第六章,“交易优势是一个数字,这是计算公式” 中重用了盈利预期的代码。

SQN 是常规 t-统计量,以盈利预期和信号计数作为输入变量。我们将交易次数的*方根乘以盈利预期的信息比率。执行交易员的英文翻译是:我们将交易频率纳入交易优势。

图 9.6:软银累计收益和 t-统计量(范·萨普 SQN):累积和滚动

如果没有交易频率,SQN 将只是夏普比率的另一种变体,而使用收益期望而不是*均回报。相反,它是一个非常有用的函数,它同时包含了交易频率和优势。例如,如果一种策略赚钱但是每隔一个闰年才交易,投资者可能不会坚持下去。相反,如果一种策略在从每天到 1 小时的较低时间框架中保持相同的正面优势,那么交易更低的时间框架以更快地复利利润将更有意义。

稳健性分数

"马萨拉:用于印度烹饪的各种混合香料。"

– 韦氏词典

坚韧指数、常识比率和范·塞尔普的 SQN 都衡量了稳健性。坚韧指数可能是非金融人士最优雅和易于理解的度量标准。CSR 是一个很好的预警指标,可以查找可疑的均值回归策略。SQN 是一个可靠的质量指标。它们都起作用。它们衡量稳健性的特定方面:

  1. 坚韧指数整合了整个周期的损失。它为所有下行方面的表现提供了准确的视野:幅度、频率和持续时间。

  2. CSR 将两种类型策略固有的风险组合到一个单一度量中。它显示了每个度量标准的风险如何*衡。

  3. t-统计量 SQN 将交易频率纳入交易优势公式中,以显示资本的最有效使用。

然而,在公开抨击风险指标泛滥之后,提出三个稳健性度量标准可能会显得有点虚伪。最简单的解决方案是将它们全部放在一起,然后使用乘法的传递性搅拌:

def robustness_score(grit,csr,sqn): 
    start_date = max(grit[pd.notnull(grit)].index[0],
               csr[pd.notnull(csr)].index[0],
               sqn[pd.notnull(sqn)].index[0])
    score = grit * csr * sqn / (grit[start_date] * csr[start_date] *
    sqn[start_date])
    return score

df['score_roll'] = robustness_score(grit = df['grit_roll'], csr = df['csr_roll'],sqn= df['sqn_roll'])
df['score'] = robustness_score(grit = df['grit'],csr = df['csr'],sqn = df['sqn'])
df[window:][['tt_cumul','score','score_roll']].plot(
    secondary_y= ['score'],figsize=(20,6),style = ['b','k','k-.'], 
title= str(ticker)+' Cumulative Returns and Robustness Score: cumulative & rolling '+ str(window)+' days') 

坚韧分数函数将所有变量重新基于第一个日期,该日期上所有变量均不为空值。这将所有变量置于相同的起始值。我们制作以下图表:

图 9.7:软银的稳健性评分:滚动和累积

稳健性分数度量旨在满足希望拥有一个统治一切的最终分数的参与者,或更有可能是希望对多个策略进行排名的一个排序关键。这个分数像弗兰肯斯坦一样重新组合,因此很难阅读。每个风险指标都为表格带来了自己的价值。这就是为什么该度量标准将所有值重新基于系列的开始。将它们合并成一个单一的度量标准不会产生超级风险度量标准,但一个具体的好处是作为一个统一的排序关键。这个度量标准将优先考虑以下策略:

  1. SQN 的频繁交易

  2. 由于坚韧指数而拥有可接受的回撤

  3. 产生可观的回报

相反,它将惩罚以下策略:

  1. 由于所有度量标准而没有积极的交易优势

  2. 由于 CSR 指数而具有恶劣的尾部比率

  3. 由于 SQN 而交易不频繁

只要移动*均指标保持在 1 以上,并且数值似乎在上升,该策略就可以被认为是相当健壮的。这种鲁棒性评分的用例之一可能是作为排序或资产配置目的的排序关键字。当有几个指标可供选择时,将它们合并成一个统一的重新基准指标并排序。但在投入生产之前,请小心谨慎。在投入生产之前,请先熟悉它。

摘要

在这一章中,我们没有就风险进行客套的谈话。我们探讨了一些毫不留情地评估您活下去的能力的风险指标。我们考虑了“毅力指数”,它综合了回撤(幅度、频率和持续时间)。然后,我们介绍了常识比率,它重新捕捉了趋势跟随和均值回归策略特定的风险。最后,我们看了系统质量数字比率,然后将这三个指标组合成一个综合的鲁棒性评分,帮助通过结合交易频率和交易优势来评估风险。

第二部分外在游戏:打造强大的交易优势中,我们看到了如何在空头市场上生成想法。然后我们看了一下交易优势到底是什么,以及如何提升它。我们提出了一种创新的股票交易算法。最后,我们看了一下真正衡量鲁棒性的风险指标。

现在我们在两个方面都有大量的想法,并且知道如何对它们进行大小和优先级排序,是时候组织它们了。第三部分多空游戏:构建多空产品,关于多空投资组合的构建。

第十章:优化投资范围

市场参与者通常觉得市场的广大相当令人生畏。因此,在我们开始将我们在前几章中涵盖的想法转化为结合的投资策略之前,我们将专门撰写一个简短的章节,将市场简化为可管理的投资范围。

在本章中,我们将从一些概念性的盲点开始,讨论长/短期业务,试图为你将要进行交易的现实世界提供一些有价值的背景信息。接下来,我们将跟随资金的脚步,通过考虑一些重大事件和主题,揭示投资者真正想要的是什么,以及这些事件和主题如何塑造交易者和市场运作的方式。

我们将涵盖以下主题:

  • 避免做空陷阱

  • 投资者真正想要什么?

避免做空陷阱

这一部分主要讲述的是应用智能过滤器来避免经典做空陷阱。随着从业者对做空变得更加熟悉,他们可能会重新审视其中一些要点。这里的大多数要点都来自于痛苦的经历。

流动性和市场影响

流动性是熊市的货币。如果你在没有重大市场影响的情况下无法退出一个头寸,那么你什么都不拥有,它拥有你。处理做空方面的流动性方式是完全不同的。在做多方面,随着更多投资者被吸引到不断上涨的价格中,流动性增加。早期的鸟儿最终会将头寸出售给一个更大的市场参与者群体。

在做空方面,当投资者清算他们的头寸时,这是一条单行道。经历了一次打击后,他们不会再回来进行第二轮。没有什么比 Kübler-Ross 模型更能真实地捕捉到长期市场参与者的情感之旅了。市场参与者为他们的损失而悲伤。甚至每个阶段在市场上都有独特的标志。兴趣减弱,随着市场参与者的减少,流动性也减少。早期的熊市比后期的熊市更具流动性。做空者离场时的流动性要比他们进场时的更低。

加入做空陷阱,你就有了一种制造爆炸性鸡尾酒的配方。你最不希望的是被困在一个大头寸的做空陷阱中,而没有办法在没有严重市场影响的情况下进行套保。在做空方面,处理流动性和市场影响的方式不是关于建立头寸所需的时间有多长,而是关于退出的难易程度。

这将投资范围限制在流动性不是问题的问题上。2008 年金融危机的解决使市场上瘾于量化宽松,也就是所谓的免费资金。简而言之,货币当局向世界注入止痛药,以缓解经济危机的痛苦。一旦货币当局暗示要逐渐停止,市场就会在撤资中螺旋下降,交易者会涌向更安全、更防御性更强的股票,这被称为“避险”。这迫使货币骑兵继续向系统注入更多的止痛药,这使得各种投机资产深陷泡沫领域。当风险是“开放的”,交易者正在寻找风险更高、利润潜力更大的股票时,中小市值股票就是行动发生的地方。与此同时,在空头方面,无聊的蓝筹股已经过时。当失败没有责任时,就没有安全玩法的动机。当风险是“关闭的”,市场参与者更多地投资于防御性更强的大型资本化公司,流动性仍然充裕。恢复长期小市值/短期大市值交易并不容易。空头中小市值股票是一项血腥的运动。流动性蒸发了,您可以在买卖价差中停泊一个超大型油轮。因此,利润可能会在第一次挤压时被抹去。

底线:将您的净市场敞口与一般市场环境和流动性水*相匹配。无论某些想法看起来多么诱人,只保留那些流动性不是问题的想法。

拥挤的空头

"猫王已经离开大厦。"

早在 2007 年,我就开发了一种名为“挤压盒子”(WMSD)的大规模空头毁灭武器。机制可能有违直觉,但它具有超现实的准确率来预测潜在的空头挤压。所需的只是一个仅持有多头的经理来持有微小的投机性长头寸。由于买卖*衡已经失衡,这将推动价格上涨并将游客冲出。他们会疯狂地买回,这将迅速演变成一次空头挤压。此时,仅持有多头的经理将轻松地退出他们的多头寸,获得舒适的利润。当我意识到这个程序直接伤害到我在对冲基金界的朋友时,这个 WMSD 被永久拆除了。

故事的寓意:从您的投资范围中消除所有拥挤的空头,借入利用率超过 50%的问题。它们甚至不应该出现在您的雷达上。想想那些经常闯红灯的人。一切都很顺利,直到他们在医院醒来。

赚钱的方法在卖空方面是找到机构投资者正在清算的东西,并跟随他们。 好的卖空故事通常弥补了不好的卖空交易。 每一点信息都附有一个刻板的价格标签。 不要等待所有的拼图拼合在一起。 当一个故事恶化到足以成为明显的卖空候选人时,机构投资者将清算他们的多头头寸。 唯一剩下的人将是争夺干枯骨头的卖空者。 这将引导我们使用一个简单而强大的供求指标,称为借款利用率

借款利用率是用于卖空的借入量与可借供应股票量之比。 大型机构拥有借贷计划,他们出借他们的长期持有部分以换取费用。 当他们削减这些头寸时,供应就会枯竭。

图

与此同时,随着卖空的流行,对借款的需求增加。 分子上的需求和分母上的供应是使借款利用率成为衡量机构所有权和流行度的最有效指标。 例如,借款利用率超过 50%仅意味着卖空欲望超过机构所有权。 由于机构是市场的主要参与者,风险/收益比显然会恶化。

根据公司的所有权结构,借款利用率可能会有很大的变化。 一些股东不参与借贷计划。 例如,持股密集的公司拥有很少的股东,这些股东由于不可言喻的原因经常无法欣赏到他们的宝贝成为恶意空头攻击的目标。

卖空是一项昂贵的运动。 卖空者要支付借款费用。 这些费用从普通担保GC)的容易借入问题到难以借入或拥挤的空头问题的高利率都有。 随着借入逐渐减少,剩余池的质量会恶化。 更糟糕的是,难以借入的问题不仅仅可以获得高利率,使得莎士比亚的夏洛克都会脸红; 有时它们是可召回的。 这意味着出借人有权选择在短时间内撤回他们的借款。 这被称为“召回”。 当发生召回时,卖空者要么留在别处寻找借款,要么*仓。 召回有时会引发卖空压力。

最后一批做空游客往往过于兴奋,无暇考虑借入可召回的股票。一旦发生召回,他们无法定位借入,被迫*仓。由于卖出压力已经达到高潮,新的买入压力造成了供需失衡。股价轻松上涨。这触发了其他做空者止损,然后他们进行回补。这迅速演变成了一场全面的做空激励,不仅冲走了游客,也冲走了更有经验的做空者。底线是:远离其他做空者涉及低质量借入的问题。

拥挤的做空股票往往对市场的敏感性较低,比较热门的问题。当市场遭遇周期性的空当时,拥挤的做空几乎不动。与此同时,牛市中的高飞股票暴跌。相对而言,这意味着拥挤的做空表现优异,而做多则表现不佳。对于这种现象的一个可能解释是缺乏机构和零售投资者的参与。拥挤的做空中没有机构长期投资,因此当周期性回调发生时,没有人出售并推动股价下跌。底线:当拥挤的做空大幅下跌时,它们不会增强做多头寸。如果拥挤的做空者带来的唯一好处是满足昂贵的正确需要,那么这不是你应该采取的方法。

结论:就像节食者需要将冰淇淋和薯片远离手边一样,完全摒弃拥挤的做空股票。

高股息率的肥沃土壤

"他们说最好的武器是你从未必须开火的武器。我尊重地不同意。我更喜欢只需开火一次的武器。"

– 托尼·斯塔克,《钢铁侠》

有时公司会增加其股息率以支撑股价。高股息率吸引了寻找更稳定现金流的价值投资者和零售投资者。这有效地阻止了做空者从事熊市活动。然而,尽管高股息率可能遏制了即时的做空压力,但它并不能阻止股价在长期内下跌。高股息率通常与停止增长的公司等同。它们已经停止增长,因此将现金重新分配给股东。这就是使高股息率股票领域成为盈利和*静做空的肥沃土壤的原因。

关于股息的好消息是它们是可预测的公司事件。有一些事件是做空者需要注意的。前两个是股权登记日和支付日。在这些时刻,做空者需要克制自己的热情。有时公司会决定在它们发布收益公告时提高股息。围绕这些日期安排交易,你会有一个惊喜的愉快时光。例如,投资者往往会在股息宣告日后立即减持。这加剧了进入股息支付日的下跌。

另一种将高收益股票重新定位为可行的做空候选者的方法是专注于导致股息一开始就很高的根本原因。成长型股票通常具有糟糕的股息收益率。它们需要现金来重新投资其业务。另一方面,稳定的成熟公司有多余的现金但长期前景不佳。少量的股息可以吸引投资者。

底线:价值陷阱隐藏在高股息之后。寻找高收益的表现不佳者,并在股息日期周围航行,你会发现时间过得惊人轻松。

股票回购

“一个人通常有两个做一件事的理由。一个听起来不错的,一个是真正的。”

– 摩根大通

按照常规智慧,公司会在其股票被低估时在开放市场上回购股票。实际上,当涉及到时机不当的估值时,他们和卖方分析师一样毫无头绪。股票回购在 2007 年底达到峰值,2009 年 3 月触底。

支持股票回购的人认为,用他们的现金和廉价信贷来回购股票是没有比这更好的用途。这会产生涓涓细流的效应,惠及整个经济。

这种股东至上主义可以追溯到 80 年代由弗里德曼在 80 年代开创的一种思想流派。通过回购股票计划,公司已成为市场上越来越重要的参与者。前总统特朗普减税后的反弹主要是由公司回购自己的股票推动的。

对手们认为,现金从利益相关者(员工、客户、研发和供应商)那里被转移出来,然后转移到股东那里。简单地说,教练对球员斤斤计较,但对球迷慷慨解囊。大多数高管的薪酬来自股票期权。因此,他们有直接的激励来支持股价以填补他们的股票期权计划。最有效的方法是回购股票。这降低了流动性,膨胀了每股收益,并推高了股价。

2020 年的冠状病毒大流行粗暴地揭示了这种虚伪,并最终解决了争论。股票回购抽干了公司的生命力。这种对短期市场影响的过度关注与公司的长期利益不一致。当世界陷入封锁时,公司几乎立即发现自己资不抵债。他们的股价暴跌,但他们仍然不得不面对为回购而签订的贷款义务。在资本主义的历史上,皇帝从未如此茫然地四处游荡,赤裸裸地出现。

但是,对于卖空者来说,这并不是重点。公司的资金实力足以人为提升股价。因此,卖空者应避免对参与股票回购计划的公司进行卖空。好消息是,股票回购与市场波动高度相关。股票回购在最需要的时候,即在修正期间会消失。这意味着卖空季节已经开始并进入全面发展阶段。

底线:不要直接做空推出股票回购的公司。让它们自我腐蚀,并等待必然的脆弱性。

基本分析

"时间在我这边。"

– 米克·贾格

基本分析为股市分析赋予了贵族的头衔。很少有事业像股票分析那样具有智力刺激性。市场体制的定义可以极大地简化基本分析的工作。

当基本分析师考虑市场体制时,他们实际上试图回答一个理论性问题。他们试图弄清楚为什么一支股票应该下跌,以及为什么现在应该发生这种情况。有很多原因。

他们最终可能会得到伸张正义。然而,他们承担了巨大的时间、声誉和最终业务风险。他们希望市场在投资者失去耐心之前同意他们的论点。期望获得一致的结果是不现实的,因为有太多的随机变量。

另一方面,将基本分析置于市场体制之下试图回答一个实际问题:为什么这支股票下跌?好消息是,答案通常可以归结为以下三个方面之一:

  • 首先,这可能是暂时的错定价格。市场可能已经从牛市转向横盘。在一个活跃的牛市阶段之后,股票往往会暂停并消化进展。这个阶段被称为整理。股票可能有一段时间不涨不跌。如果是这样,解决方案很简单。待命的空头头寸看起来在经历了大幅度的回调之后会好很多。减持你的头寸。将资本重新配置到新的想法上。如果股票重新开始表现,将有充裕的时间重新建仓。

  • 其次,如果一个行业内的几只股票开始齐头并进地表现不佳,这表明行业轮动。这减轻了分析师的工作负担:选择几乎任何一个表现不佳的行业的股票。

  • 第三,如果一只股票的行为与其行业不符,这可能表明存在一些股票特定的问题。这是基本分析师大展身手的时候。这是发现真正有利可图的结构性空头的时候。价值陷阱经常被忽视,因为它们具有价值股票的所有外部特征。它们经常有慷慨的股息政策。相对于同行,估值打了折扣,这使它们在表面上看起来很有吸引力。然而,它们顽固地表现不佳。它们之所以便宜并且保持便宜是有原因的。基本分析师的工作是找出原因。

在卖空方面,传统的基本分析很难进行。信息的不对称是卖空者必须应对的问题。公司很少自愿公布坏消息。分析师保持他们的“买入”评级,直到命运的那一天,他们碰巧在媒体上读到公司前一天晚上申请破产的消息。

卖方拉拉队可能会有一些不情愿的边际效用。在误导性的“买入”评级的多年冻土草原上,低表现的暗号是“为长期投资者购买”。寻找评级不更新、收益模型积满灰尘的股票,甚至连维护研究都没有得到适当的维护。只需一个电话确认“那些是长期投资者的股票”,你就可以开展业务。

投资者真正想要什么?

长/短行业似乎每次市场“出现疲软迹象”时都会经历严重的存在危机。投资者被粗鲁地提醒,下行保护仅意味着几乎没有上行的有限下行。该行业一直是从“建立它们就会来”的产品供应模式运作的。如果目标是建立可持续的业务,那么是时候暂停一下,从投资者的角度审视世界了。这将为建立符合投资者需求的长/短产品提供至关重要的背景。

从 2007 年量化灾难中得到的教训

“于是,由沙子建造的城堡,

融入海洋,

最终。

—— 吉米·亨德里克斯

2007 年 8 月,横截面波动性让全球市场大吃一惊。虽然指数波动不大,但成分股在几天内纷纷跃升。很快,关于各种量化市场中性基金解除交易的传言开始传播。这标志着量化 1.0 的终结。

那些聪明的市场中性基金就像威尼斯比萨饼一样:菜单上有 37 种不同的名称,但每个人的面团都是一样的。它们的模型相当相似。由于它们是市场中性的,来自卖空的现金收益可以用来几乎无限地进行杠杆。一些基金将杠杆倍增到七倍,以放大原本乏味的回报。一段时间以来,一切都运作良好。所有基金经理所需要做的就是继续卖空更多股票,以匹配不断扩张的多头。这一切都进行得很顺利,直到 2007 年夏天,房地产泡沫开始腐烂。

每场雪崩都是由一个雪球开始的。那时,在市场的另一个角落,一些大型多策略交易公司被要求为他们的信用违约义务CDO)和信用违约掉期CDS)组合提供更多的抵押品。当他们无法为信贷账本筹集现金时,他们被迫清算他们最流动的资产类别。他们转向他们的量化市场中性账本。这是最初的雪球。在夏季中旬,流动性通常会枯竭。他们的空头账本不流动。当第一个商店开始*仓时,他们抬高了价格。这触发了他们邻居的止损。他们继续关闭自己的头寸。这引发了连锁反应,最终导致了混乱的横截面市场。这就是传染的定义。

人们有时会就什么构成良好质量而争论,但他们很少在糟糕的东西上产生分歧。每个人都发现自己处于同一糟糕境地。由于可用于卖空的股票有限,交易变得非常拥挤。多策略基金的清算加剧了问题。管理者最终意识到,解除空头头寸需要数周时间,他们开始将头寸减少到可控水*。流动性是主要风险。几乎所有人都在大致相同的模型下同时得出了相同的结论。匆忙*仓的精英量化交易员堪比金融版的大象在瓷器店里乱窜。

那时,市场中性基金被宣传为安全的投资工具:股票回报与低波动性。在许多人心中,市场中性意味着资本保护。因此,当一些基金在看似*静的市场上发布-3-4%的月度回报时,发生了两件事。首先,由于风险价值VAR)增加,主要经纪商提高了保证金要求,迫使基金减少杠杆。其次,投资者让基金经理们苦恼不已:“救赎之歌”。

这些赎回迫使管理者关闭头寸,给基金增加了更多的波动性。减少了杠杆,增加了波动性,并且不断增加的赎回,将需要数月,甚至数年的时间来弥补损失。而且,声誉损失是不可挽回的。对于量化市场中性基金 1.0 来说,游戏已经结束。

这场崩溃始于一个简单的错误:那些基金的设计者犯了一个致命的假设,即空头将会与多头一致。有一段时间,确实如此。但随着基金规模的扩大,空头的独特动态回来困扰着他们。流动性枯竭了。空头变得拥挤。等到管理者意识到空头风险呈指数增长时,已经为时太晚了。

故事的寓意:如果你想经营一个可持续的多空业务,你需要从空头开始构建你的投资组合。

有关这个主题的更多信息,请参阅 Lehman Brothers 的 Matthew S. Rothman 博士于 2007 年 8 月 9 日撰写的《量化领域的动荡时期》。

接下来的两部分将进一步关注投资者真正想要的是什么。他们不是将资金放在复杂的长/空中,以购买低技术的交易所交易基金ETF)所能做到的同样的苹果公司(AAPL)股票,后者成本只有一小部分。投资者希望低波动性的回报与市场波动不相关。

长/空行业的绿黄蜂综合症

“真实存在的比应该存在的更重要。太多人从应该是的角度看待真实存在。”

– 布鲁斯·李,伟大的华裔美国哲学家

1966 年的电视系列剧《绿黄蜂》以布雷特·里德为特色,他白天是《每日哨兵报》的雄心勃勃的出版商,晚上则是作战的绿黄蜂,而他的忠实男仆卡托则是忠诚的。如果不是因为一位名叫布鲁斯·李的未知演员扮演的副手管家,那个很快被遗忘的节目永远不会进入那些神秘系列的世界。

长/空行业患有未解决的绿黄蜂综合症。许多长/空参与者是披着狼皮的羊。机敏灵活的对冲基金经理喜欢吹嘘自己在多头方面选择股票的优越分析能力。谁在乎呢?没有人需要对冲基金经理繁琐的“复杂性”来购买苹果公司。任何“无聊”的纯多头基金经理都将以较低的成本提供完全相同的服务。更好的是,任何低技术、低成本的普通香草 ETF 都会比任何主动管理者在时间上做得更好。

长/空市场参与者真正进入神话般的基金经理的阵容的是他们在其他人都不赚钱时赚钱的能力。这来自于被称为空头账簿的副手。

长/空行业是一个竞争激烈的领域。市场参与者知道他们必须立即开始吸引投资者。因此,他们默认在自己的舒适区内交易。他们大部分时间都在选择多头方面的股票。与此同时,对空头的无尽挫折使他们放弃了学习“黑暗艺术”的细节。尽管最初的意图是最好的,但空头账簿逐渐被边缘化为一种次要表演。

随着市场上涨,这种情况就会持续下去。一旦市场陷入“软墙”,被忽视的空头方无法弥补多头方的损失。当业绩出现突然下滑时,投资者会感到窒息。他们不得不忍受过高的费用,并容忍“alpha 挑战”式的回报。难怪当他们意识到下行保护实际上意味着损失少于市场时,他们会感到窒息。因此,长/空行业受到越来越多的愤世嫉俗的对待,也就不足为奇了。

从伯尼·麦道夫那里学到的教训

“当你看到我多次欺骗骗子和傻瓜而没有丝毫良心负担时,你会感到很有趣。”

– 贾科莫·卡萨诺瓦

每个市场参与者都有一些能产生阿尔法收益的“秘密武器”。他们相应地推出适合自己投资风格的产品。他们奉行“建造它,他们就会来”的模式,相信仅靠阿尔法收益就足以吸引投资者。很快,他们就会想知道为什么其他具有*稳回报的参与者在激烈的资产管理竞争中超越了表现出色的市场巫师。

作为一种资产类别,系统性商品交易顾问(CTAs)几十年来一直主导着表现赛道。然而,根据朋友和畅销书作者迈克尔·科维尔的说法,他们的总资产管理规模占全球资产管理总规模的 0.4%。尽管长期表现优异,但他们的总资产管理规模仍然是一个可以忽略的数字。这让基金经理感到困惑。一方面,投资者们公开表示他们在寻找回报。另一方面,当到了付诸实践的时候,他们选择了其他的东西。好消息是金钱留下了痕迹。

在赞扬马多夫先生的营销才华之前,让我们搞清楚一件事。任何欺诈投资者的白领罪犯都应该在监狱里待上几十年。伯纳德·L·马多夫是私人部门小联盟中最伟大的骗子之一。几十年来,他欺骗了成千上万的投资者数十亿美元。他的故事为投资者的心态提供了宝贵的见解。

马多夫所提供的东西是如此强大,以至于它削弱了金融业一些最复杂的参与者的专业怀疑。在一次难得的监狱采访中,马多夫先生承认投资者“本应该知道更多”。下面是马多夫所谓的回报表:

标准普尔 500 指数 费尔菲尔德信托公司(马多夫)
年*均回报 7.7% 11.0%
复合回报 201.0% 504.0%
正收益月份 63.0% 92.0%
最大回撤 -46.3% -1.6%
回撤持续时间(月) 80 2
半相关 0.03

*均每年 11.04%的表现还算不错,但并非惊人。正如之前提到的,投资者们声称他们想要回报,但他们对回撤作出了反应。马多夫与众不同的地方在于有四点:

  • 首先,回撤的持续时间:绝不能考验投资者的耐心。从零售投资者到机构资产配置者,每个投资者脑海中都有一个挥之不去的问题:“现在投资还来得及吗?”只有当贪婪或错过机会的恐惧比害怕赔钱更强烈时,他们才会把自己辛苦挣来的积蓄投入使用。在实践中,高峰时期的资金流入往往与牛市的顶峰相一致。那些订阅了“道指涨至 36,000 点”骗局并在 2000 年 8 月冒险投资的幼稚者,在他们在 2007 年 5 月收回资金之前,不得不忍受 80 个连续月的回撤。那正好是下一次暴跌的时间。相比之下,麦道夫先生总是营业。他只有连续两个月的回撤。每个月都是进入市场的好时机。这样短的回撤持续时间在统计学上是不太可能的。唯一接*的市场参与者是传奇人物爱德华·索普,讽刺的是他在丑闻爆发前 14 年就揭露了麦道夫。

  • 第二是回撤的幅度:绝不能考验投资者的胃口。一旦陷入回撤,投资者会担心情况会变得有多糟糕。市场长期*均回报率可能为 7%,方便地忽略了其中的-40-50%的巨大回撤。即使正回报并不惊人,-1.56%的最大回撤使其看起来像是一种无风险投资。康尼曼-特沃斯基以更加精彩的方式制定了他们的前景理论:厌恶损失比追求利润更为强大。这说明了一个强大的概念:“你赚多少钱并不重要,只要你不亏损。”投资者可以设定并忘记。

  • 第三是回撤的频率:绝不能考验投资者的神经。据说麦道夫的表现有 92%的时间是赚钱的,而标普指数只有 63%。标普指数有 6 年的年度回报率超过 20%。它也有 4 年的负双位数回报率。相比之下,麦道夫的欺诈*均回报率是 11.04%。然而,标普指数的复合回报率是 200%,而麦道夫的是 500%。

  • 第四是半相关性(与标普指数下跌月份的相关性),或者在下跌市场中赚钱的能力。据称,麦道夫的半相关性是 3%,即每当市场下跌时他都能赚钱。这就敲定了交易。在所有人都跌倒时仍然屹立不倒的经理们脱颖而出。他们的电话响个不停,有意向的投资者络绎不绝。

在现实世界中,像麦道夫那样获得回报是统计学上不太可能的。然而,你越接*,你的提议就越具有吸引力。如果你成功地建立了一个介于麦道夫的圣杯和指数被动投资之间的产品,你将比竞争对手更具竞争力。

总结

这个简短的章节并不意味着要考验读者的脑细胞。它只是一个关于如何避免经典昂贵陷阱并满足投资者期望的实用提示集合。投资者不是为了长期想法而购买多空产品。他们想要低波动性的不相关回报。这一章考虑了投资者的期望,同时避免了将空头书籍视为更有趣的多头书籍的陷阱。如果将那些问题股票从你的视野中清除,它们就不会在你的脑海中出现,这将消除诱惑。

一旦你压缩了你的投资领域并了解了投资者对你的期望,就是时候扣动扳机了。在接下来的章节中,我们将把所有的东西整合起来,看看如何在实践中做到这一点。

第十一章:多空工具箱

仅多头投资组合从定义上来说与市场相关。引入空头组件使得管理者能够设计他们想要实现的绩效类型。我们将在本章中使多空投资组合管理对所有专注的市场参与者都可达。

创建一个多空投资组合需要合并两个相对组合:一个多头和一个空头。从仅多头或绝对多空转向相对强度多空投资组合一开始可能会让人感到不安。有许多动态因素。管理这种转变的有效方法是从目标出发:流动性、相关性、波动性和绩效。然后,专注于几个对这些目标影响最大的变量:总曝光和净曝光、净 beta 和浓度,它们构成了您在构建策略时的投资工具箱。

以下表格指示了这些变量中的每一个对我们的目标产生的影响。

流动性 相关性 波动性 表现
总曝光
净曝光
净 beta
浓度

最后,我们实践我们所写下的。是时候进行一些有纪律的创造了,为您构建自己的投资策略提供逐步指南。在这个过程中,我们将涵盖以下主题:

  • 导入库

  • 总曝光:杠杆的战术性方法

  • 净曝光:标题性的看涨/看跌方向性

  • 净 beta:对市场的剩余敏感性

  • 浓度:每一边的股票数量

  • 其他曝光

  • 设计您自己的授权

让我们从总曝光开始。这是您愿意承担的杠杆量。杠杆是一把强大的双刃剑。如果不正确使用,它会创造然后毁灭一个企业。

您可以通过以下链接访问本章所有图片的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。您也可以通过该书的 GitHub 存储库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

对于本章和本书的其余部分,我们将使用 pandasnumpyyfinancematplotlib 库。因此,请记得首先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt 

总曝光

总敞口是多头和空头头寸的绝对总和。卖空股票会产生现金,可以用于进入更多的多头头寸。理论上,杠杆可以无限增加。实际上,主要经纪人限制杠杆为 3 或 4 倍,以限制他们的交易对手风险。没有人希望在市场出现迹象时立即处理保证金调用。

总敞口对以下方面直接产生影响:

  • 流动性:杠杆越高,持仓规模越大。这直接影响市场影响力。这在卖空方面尤为明显,就像 2007 年的量化交易员所证实的那样。

  • 波动性:杠杆放大了回报的波动性。

  • 绩效:杠杆放大了回报:低杠杆下微不足道的 0.1%可以增加到 0.5%等等。

  • 集中度:如果目标是保持波动率低,那么名字的数量应该与杠杆成比例地增加:总敞口增加意味着更多的名字,反之亦然。

总敞口最终反映了市场参与者对市场的信心。他们越自信,就越倾向于增加杠杆以抓住机会。在科技泡沫中,没有什么比增长型经理更像是糖果店里的孩子。相反,在动荡或不确定时期,市场参与者倾向于减少总敞口并增加现金敞口以保护资本。战略性地管理总敞口可以是在好时机提高绩效和在困难市场保护资本的强大工具。

市场参与者倾向于以以下两种方式管理总敞口。他们要么坚持固定的敞口水*,要么采取非结构化的方法。固定敞口的参与者在整个周期内保持相同水*的总敞口。保持固定总敞口水*的理由是简单性。参与者喜欢将名字数量保持在一个可以安全管理的水*上。在好时期他们可能会损失一些收益,但在连续亏损期间,他们可以将回撤保持在可控水*。另一方面,非结构化的参与者在好时期变得乐观,增加头寸,而在坏时期则囤积现金。

如果你的目标是以相对较低的波动率提供有吸引力的回报,可能会有一种更科学的方法。在接下来的章节中,我们将考虑一种简单、有效、分步骤的管理总敞口的方法。这个想法是允许总敞口跟随你的绩效周期。这被称为管理投资组合热度。

投资组合热度

第二部分外部游戏:制定稳健的交易边缘中,我们在进入交易之前讨论了头寸规模和风险管理。当我们已经投资并且市场意外地出现不愉快的转变时会发生什么?市场是生活的一个很好的反映。这就是当我们有其他计划时发生的事情。

我们既不能预测也不能控制世界上发生的事情。那些仍然相信自己可以预测任何事情的人肯定不应该负责管理养老基金。然而,我们可以通过以下两种方式控制投资组合中发生的事情:

  • 首先,我们可以通过头寸大小控制投资组合中的风险量。在进入头寸之前,我们完全控制着将分配给下一笔交易的风险量。

  • 其次,我们可以控制投资组合中所容忍的风险量。这些是现有的头寸。一些工作,一些不工作。一些脆弱。一些仍然处于风险之中。一些是无风险的。

这引出了开放风险、投资组合热度和相关性的概念:

  • 开放风险是股票级别的潜在损耗。如果触发了止损,该头寸将以亏损还是盈利的方式关闭?如果是盈利的话,开放风险就是零。在金融业术语中,该头寸被称为自由携带。不管接下来发生什么,交易都不会亏钱。

  • 投资组合热度是所有头寸上的开放风险的总和。开放风险是按方向和策略汇总的。例如,假设您进行了两种长/短策略交易:一种是均值回归,一种是趋势跟随。分别汇总这四个开放风险和资产曲线。在这种情况下,开放风险和最大潜在回撤是两码事。开放风险中的投资组合热度仅处理脆弱头寸。自由携带头寸受到一套不同的规则的约束。

  • 相关性是长期书籍与短期书籍在总体上的运动方式。当市场下跌时,短期书籍并不总是带头。例如,长期股票的投机性问题下降得比低β股票更快更远。关键是假设“相关性趋于 1”,意味着一切都像板砖一样下跌。长期和短期投资组合的热度并不会互相抵消。理论上,人们会认为短期投资组合会弥补长期投资组合的下跌。实际上,在市场回调期间,做空有时会胜过做多。惊慌的动量买家抛售他们的长期持仓,从而导致价格下跌。因此,不要抵消长期和短期投资组合的热度。

投资组合热度需要保持在范围内。接下来,让我们看一下设定热度范围的几个一般原则。

投资组合热度范围

如果你承担了太多的风险,总有一天你就不会有生意可做。如果你没有承担足够的风险,你根本就不会有生意可做。因此,秘诀在于保持风险在范围内。

最大热度带应该定义如下。目标不是在全面减少总体敞口。目标是在头寸级别减少开放风险,这将导致总体敞口的收缩。股票具有不同的波动性特征。低波动性股票需要更大的头寸。例如,在防御性股票上减少风险与在高波动性股票上减少风险的影响大相径庭。这个系统比实际总体敞口带更有效。市场参与者应该牢记投资组合热度的上限。

存在一个理性的最大风险数字,可以确保资产曲线的最佳几何增长率。很好,但完全无关紧要。重要的是你的客户可以容忍多少风险。例如,如果客户表示可以接受 10%的回撤,那么您的可接受最大投资组合热度应该在 5%左右。总的来说,人们,尤其是客户,都极大地高估了他们对痛苦的耐受能力。此外,纠正局势需要时间和精力。上限实际上是一个业务决策。波动性是风险的副产品——在投资组合层面容忍的风险越多,投资组合中引入的波动性就越多。这将限制您能够针对的客户类型。例如,养老基金是厌恶波动性的。它将决定从数量到绩效和信息比率的一切。

当有疑问时,应该慎重行事。一个经典的解决方案是增加名称的数量,例如。此外,正如我们将在战术部署部分看到的那样,投资者是按照日历年来思考的。因此,您的上限容忍度根据是年初还是年底接*而变化。一切相等,风险应该从小开始,逐渐增加,在第三季度达到顶峰,到年底逐渐减少。将惊喜留给圣诞礼物,而不是给您的投资者的钱。

最小值可以这样定义。长/短经理最终根据其保护资本的能力进行评判。您的系统必须能够通过回撤交易。一个简单的经验法则是将最小值设定为最大值的一半。如果您预计投资者会在 10%的回撤时赎回您的份额,那么您的最大值应该约为 5%,最小值为 2.5%。

最坏的情况是,在重新回到原点之前,您可能会遭受 7.5%的回撤。此外,一旦绩效好转,第八章中介绍的凸性振荡器,头寸规模:资金管理模块中的金钱赚钱,将重新加速。

即使投资组合热量的差异看起来很小,对总风险敞口的影响可能看起来更加戏剧化。投资组合热量的+/-0.1%的差异很容易使总风险敞口产生 5-10%的变动。这将直接影响波动性、绩效和流动性,如市场影响所示。在实践中,这项技能有一些魔力。投资者将会看到纪律性的风险管理,这最终是他们愿意付出好钱的技能。

战术部署

牛市可能持续数年,但投资者倾向于以季度和年度时间段思考。如果投资者以日历年为单位思考,那么你也应该如此。因此,杠杆应该在整年战略性地部署。如果你在年初杠杆被搞得很高,而绩效一开始就大幅下滑,那么你将在余下的时间里不断地摆脱困境,而投资者则紧盯着你。压力对于做出良好的决策是不利的。另一方面,一旦你建立了绩效,就会有余地来运用杠杆。所以,每年都从最小杠杆开始。一年可能会开始缓慢。投资者会忘记一个缓慢的开始,但他们不会原谅一个艰难的开始。

相反,随着年末的临*,逐渐减少杠杆以在下一个周期开始时达到最小杠杆。投资组合热量的季节性管理在数学上没有意义。投资者很少在抽象数学中竞争诺贝尔奖。他们是人类。他们用直觉反应。

逐步投资组合热量和敞口管理

第八章仓位大小:在资金管理模块中赚钱中,我们使用股票曲线来计算应该分配给进入投资组合的交易的风险有多少。这是在个人层面上的每笔交易的风险。现在,我们将重新审视已经在投资组合中的位置的凸面振荡器。在进入之前的微观层面(每笔交易的风险)的关系在投资组合宏观层面(投资组合热量)上仍然成立。市场不断变化,因此风险应相应调整。每笔交易的风险在股票级别上在最大和最小范围内振荡。类似地,投资组合热量在最大和最小值之间振荡。这种方法的美妙之处在于其简洁的优雅。我们不专注于头寸的大小,只关注它们的未*仓风险。这迅速减少了杠杆,同时保持了成功的无风险头寸不受影响。

实施凸面振荡器对最大投资组合热量的影响直接影响所有风险敞口。让我们用一些逐步的数字示例来说明这一点。

第一步:凸度配置

股票/微观级别有效的东西在投资组合/宏观级别也有效。整体投资组合风险称为开放风险投资组合热量。目标是尽可能长时间地以最大热度运行。随着回撤加剧,投资组合热量逐渐降低直至最低水*。此风险可以使用我们在第八章头寸规模:金钱在资金管理模块中赚取中看到的risk_appetite()函数来降低:

def risk_appetite(eqty, tolerance, mn, mx, span, shape):
    '''
    eqty: equity curve series
    tolerance: tolerance for drawdown (<0)
    mn: min risk
    mx: max risk
    span: exponential moving average to smoothe the risk_appetite
    shape: convex (>45 deg diagonal) = 1, concave (<diagonal) = -1, else: simple risk_appetite
    '''
    # drawdown rebased
    eqty = pd.Series(eqty)
    watermark = eqty.expanding().max() # all-time-high peak equity
    drawdown = eqty / watermark - 1 # drawdown from peak
    ddr = 1 - np.minimum(drawdown / tolerance,1) # drawdown rebased to tolerance from 0 to 1
    avg_ddr = ddr.ewm(span = span).mean() # span rebased drawdown

    # Shape of the curve
    if shape == 1: # 
        _power = mx/mn # convex 
    elif shape == -1 :
        _power = mn/mx # concave
    else:
        _power = 1 # raw, straight line
    ddr_power = avg_ddr ** _power # ddr 

    # mn + adjusted delta
    risk_appetite = mn + (mx - mn) * ddr_power 

    return risk_appetite 

在下面的示例中,我们将构建一个由 10 支股票组成的虚构投资组合—5 支多头,5 支空头。我们将演示如何在个股水*进行投资组合热量降低。

步骤 2:回撤重新调整

我们的假想投资组合以标普 500 指数为基准。初始资本(K)设定为 100 万美元。贝塔(对市场的敏感性)已从 Yahoo Finance 网站中提取。股票数量和相对止损已校准为相对风险调整至投资组合的-0.50%。该投资组合运行时间从 2020 年 12 月 31 日到 2021 年 6 月 30 日。首先,我们将生成数据集:

port = np.nan
K = 1000000
lot = 100
port_tickers = ['QCOM','TSLA','NFLX','DIS','PG', 'MMM','IBM','BRK-B','UPS','F']
bm_ticker= '^GSPC'
tickers_list = [bm_ticker] + port_tickers
df_data= { 
'Beta':[1.34,2,0.75,1.2,0.41,0.95,1.23,0.9,1.05,1.15],
'Shares':[-1900,-100,-400,-800,-5500,1600,1800,2800,1100,20800],
'rSL':[42.75,231,156,54.2,37.5,42.75,29.97,59.97,39.97,2.10]
}
port = pd.DataFrame(df_data,index=port_tickers)
port['Side'] = np.sign(port['Shares'])

start_dt = '2021-01-01'
end_dt = '2021-07-01'
price_df = round( yf.download(tickers= tickers_list,start= '2021-01-01' , end = '2021-07-01', interval = "1d",group_by = 'column',auto_adjust = True, prepost = True, treads = True, proxy = None)['Close'],2)

bm_cost = price_df[bm_ticker][0]
bm_price = price_df[bm_ticker][-1]

port['rCost'] = round(price_df.iloc[0,:].div(bm_cost) *1000,2)
port['rPrice'] = round(price_df.iloc[-1,:].div(bm_price) *1000,2)
port['Cost'] = price_df.iloc[0,:]
port['Price'] = price_df.iloc[-1,:]

print(port) 

这里没有什么大秘密。我们使用字典和列表创建数据帧。然后我们从 Yahoo Finance 下载价格。成本设定为 2020 年 12 月 31 日,当前价格为 6 月底。在撰写本文时,这产生了以下数据帧。

贝塔 股票 rSL 方向 rCost rPrice 成本 价格
QCOM 1.34 -1900 42.75 -1 40.16 33.26 150.85 142.93
TSLA 2.00 -100 231.00 -1 187.87 158.16 705.67 679.70
NFLX 0.75 -400 156.00 -1 143.96 122.91 540.73 528.21
DIS 1.20 -800 54.20 -1 48.24 40.90 181.18 175.77
PG 0.41 -5500 37.50 -1 36.59 31.40 137.43 134.93
MMM 0.95 1600 42.75 1 45.82 46.22 172.10 198.63
IBM 1.23 1800 29.97 1 32.71 34.11 122.85 146.59
BRK-B 0.90 2800 59.97 1 61.73 64.67 231.87 277.92
UPS 1.05 1100 39.97 1 44.34 48.39 166.54 207.97
F 1.15 20800 2.10 1 2.34 3.46 8.79 14.86

第四章长/空头方法论:绝对和相对中介绍的relative()函数有一个小区别,后者有重新调整到系列开始的选项。我们选择使用连续系列。市场参与者一直在围绕头寸交易。重新调整很快变成了不必要的计算难题。因此,使用相同日期收盘价乘以一个常数—在本例中为 1000 是有意义的。止损和所有计算都基于相对系列。

接下来,让我们计算几个重要的指标:

  • BV 代表账面价值。这是以基金货币(美元)计算的成本乘以所有开放头寸的股票数量。

  • MV 代表市值。这是调整为货币(美元)的股票数量乘以当前收盘价。

  • rMV 代表相对市值。

  • 毛暴露是基金货币中所有市值的绝对总和,除以管理资产—在本例中为 K。

  • 净暴露是所有市值的算术净总和,除以市值的绝对总和。

  • 净 Beta 是市值乘以 Beta 的总和乘以市值的绝对总和。

现在让我们看一下代码:

BV = port['Shares'] * port['Cost']
MV = port['Shares'] * port['Price']
rMV = port['Shares'] * port['rPrice']

port['rR'] = (port['rCost'] - port['rSL'])
port['Weight'] = round(MV.div(abs(MV).sum()),3)
port['rRisk'] = -round(np.maximum(0,(port['rR'] * port['Shares'])/K),4)
port['rRAR'] = round( (port['rPrice'] - port['rCost'])/port['rR'],1)
port['rCTR'] = round(port['Shares'] * (port['rPrice']-port['rCost'])/ K,4)
port['CTR'] = round(port['Shares'] * (port['Price']-port['Cost'])/ K,4)
port_long = port[port['Side']>0]
port_short = port[port['Side']<0]

concentration = (port_long['Side'].count()-port_short['Side'].count())/port['Side'].count()
gross = round(abs(MV).sum() / K,3) 
net = round(MV.sum()/abs(MV).sum(),3)
net_Beta = round((MV* port['Beta']).sum()/abs(MV).sum(),2)
print('Gross Exposure',gross,'Net Exposure',net,'Net Beta',net_Beta,'concentration',concentration)
rnet = round(rMV.sum()/abs(rMV).sum(),3)
rnet_Beta = round((rMV* port['Beta']).sum()/abs(rMV).sum(),2)
print('rGross Exposure',gross,'rNet Exposure',rnet,'rNet Beta',rnet_Beta) 

输出将类似于以下内容:

Gross Exposure 3.327 Net Exposure 0.141 Net Beta 0.24 concentration 0.0 
rGross Exposure 3.327 rNet Exposure 0.141 rNet Beta 0.24 

3.327 的毛暴露是中度到高杠杆。毛暴露为 2 意味着资产管理 (AUM) 在多头和空头方面各杠杆一次。3.327 意味着 AUM 大约杠杆了 1.6 次。净和 r 净暴露为 0.141 意味着投资组合*衡均匀且轻微看涨。净和 r 净 Beta 为 0.24 意味着投资组合在残余上是看涨的。它不容易受到任何重大冲击。

总体而言,除了高度集中和持续性开放风险外,投资组合看起来很*衡。接下来,我们计算风险:

  • R 是由 Van Tharp 博士在他的书籍《交易自由之路》中推广的一种度量方法。它简单地是成本与止损之间的差异。在这里,我们将使用相对版本的 R,或者 rR。

  • 权重是基金货币(USD)中的市值,除以市值的绝对总和。

  • r 风险是对权益的加权相对风险。该公式包含一个神秘的 np.maximum(0, (port['rR'] * port['Shares'])) 序列。一旦止损被重置超出当前止损,这将变为负数。这确保了开放风险保持为负。

  • rRAR 是以初始相对风险单位表示的相对收益。这是最真实和最简单的风险调整收益指标。这将是我们的主要工具。

  • rCTR 和 CTR 是相对和绝对贡献,或者是盈利与权益的比值。

接下来,让我们按方向和相对风险调整后的收益打印投资组合。

port[['Side', 'Weight', 'rRisk', 'rRAR', 'rCTR', 'CTR']].sort_values(by=['Side','rRAR'] ) 
方向 权重 r 风险 rRAR rCTR CTR
TSLA -1 -0.020 -0.0043 0.7 0.0030 0.0026
DIS -1 -0.042 -0.0048 1.2 0.0059 0.0043
NFLX -1 -0.063 -0.0048 1.7 0.0084 0.0050
QCOM -1 -0.082 -0.0049 2.7 0.0131 0.0150
PG -1 -0.223 -0.0050 5.7 0.0285 0.0138
MMM 1 0.095 -0.0049 0.1 0.0006 0.0424
IBM 1 0.079 -0.0049 0.5 0.0025 0.0427
UPS 1 0.069 -0.0048 0.9 0.0045 0.0456
BRK-B 1 0.234 -0.0049 1.7 0.0082 0.1289
F 1 0.093 -0.0050 4.7 0.0233 0.1263

仓位按方向和相对风险调整后的收益整齐排序。让我们使用 groupby() 方法应用于多头和空头账簿来查看汇总。

port[['Side', 'Weight', 'rRisk', 'rRAR', 'rCTR', 'CTR']].groupby('Side').sum() 

这将产生以下表格:

权重 r 风险 rRAR rCTR CTR
方向
-1 -0.43 -0.0238 12.0 0.0589 0.0407
1 0.57 -0.0245 7.9 0.0391 0.3859

这给我们带来了侧面的大量总数。两侧表现良好。预期之中,净暴露已经扩大。空头已经缩小。这种错位是健康的空头的标志。多头也增加了。总的相对风险大约为-4.8%,分布在 10 个名称中。接下来,让我们削减对表现最慢的股票的敞口。

步骤 3:按比例分配开放风险

总风险暴露为 333%,开放风险为+13.9%,净 beta 为 0.24。让我们来看一个经典案例。管理层高层中的某人在管理罕见的大气层中暂停了纸牌游戏,并决定全面减少敞口。在执行交易员的英语中,这意味着削减杠杆。在整个投资组合中削减头寸大小没有标准的配方。市场参与者可以使用几种方法。这些方法从全面减少所有头寸到在最脆弱的头寸中进行外科手术般地削减边际风险。由于任何人都可以执行前者,让我们探讨如何以最小的努力完成后者。

假设性地,我们的目标是将开放风险从-4.8%降低到-2.8%。由于开放风险均匀分布,我们将在每一侧削减 1%的风险。该代码适用于分离的风险降低,但这将保持简单。逻辑是通过使用相对风险(rRisk)作为排序键来减少大小:port_long['rRisk'] / (port_long['rRisk'].sum(). 风险越高,削减越大,依此类推。

adjust_long = adjust_short  =  -0.01 

pro_rata_long = port_long['rRisk'] / (port_long['rRisk'].sum() * port_long['rRAR'])
risk_adj_long = (abs(adjust_long) * pro_rata_long * K / port_long['rR'] // lot) * lot
shares_adj_long =  np.minimum(risk_adj_long, port_long['Shares'])*np.sign(adjust_long)

pro_rata_short = port_short['rRisk'] / (port_short['rRisk'].sum() * port_short['rRAR'])
risk_adj_short = (abs(adjust_short) * pro_rata_short * K / port_short['rR'] // lot)*lot
shares_adj_short = np.maximum(risk_adj_short,port_short['Shares'])*np.sign(adjust_short)

port['Qty_adj'] = shares_adj_short.append(shares_adj_long)
port['Shares_adj']  = port['Shares'] + port['Qty_adj']
port['rRisk_adj'] = -round(np.maximum(0,(port['rR'] * port['Shares_adj'])/K),4)
MV_adj= port['Shares_adj'] * port['Price']
rMV_adj = port['Shares_adj'] * port['rPrice']
port['Weight_adj'] = round(MV_adj.div(abs(MV_adj).sum()),3)

print(port[['Side','rRAR','rRisk','rRisk_adj','Shares','Qty_adj', 'Shares_adj', 'Weight','Weight_adj']].groupby('Side').sum()) 

首先要做的逻辑事情是先减少处于风险中的头寸。那些是最容易受到攻击的。带有止损超出成本的头寸可以暂时放过,直到所谓的通风系统面临困境。当止损超出成本时,开放风险为zero. np.maximum(0, (port['rR'] * port['Shares']))是粗糙的,但它有效。在我们的示例中,止损未被重置,所有头寸神奇地都有贡献。正如格劳乔·马克思曾经说过的:“除非老板提早离开,否则没有人会过早离开。”因此,我们仍然需要削减敞口。

我们将按侧面比例分配开放风险,并除以风险调整收益。这将根据侧面和开放风险调整收益对头寸进行排名。那些贡献最少的头寸从定义上来说是最危险的。

让我们考虑一下这段代码是如何工作的:

  1. 我们将-1%的风险降低因子纳入按比例分配中以计算股份数。我们乘以资本并除以成本和止损之间的相对距离rR,以获得确切的股份数。我们找到了模数(//)与手数相乘,以达到一个整数。

  2. 风险降低不能大于现有股份数。在多头方面,我们取股份数或调整的最小值。在空头方面,我们取股份数或调整的最大值。

  3. 我们添加一个新的列,Qty_adj,在其中我们附加要调整的股份。我们使用['Shares_adj'] = port['Shares'] + port['Qty_adj']来计算新的股份。

  4. 我们进行与之前相同的计算,以查看削减如何影响投资组合。我们打印出数据框。

这会产生一个聚合表,应该类似于以下内容(取决于您运行代码时股票的表现如何):

rRAR rRisk rRisk_adj Shares Qty_adj Shares_adj Weight Weight_adj
Side
-1 10.8 -0.0251 -0.0164 -8700 1300.0 -7400.0 -0.430 -0.511
1 7.9 -0.0245 -0.0127 28100 -5800.0 22300.0 0.571 0.490

多头方面的回报是一致的,因此需要大幅削减风险。

请注意,空头方面的调整风险尚未达到目标。正如我们将在下文看到的,表现出现了很大的差异,一些头寸几乎没有受到影响,而另一些头寸大幅减少。现在,这个示例只有少数头寸。这种不均匀的减少可能会发生。

print(port[['Side','rRAR','rRisk','rRisk_adj','Shares','Qty_adj', 'Shares_adj', 'Weight','Weight_adj']].sort_values(by=['Side','rRisk_adj' ], ascending=[True,False])) 

扩展视图会得到类似以下内容的东西。

Side rRAR rRisk rRisk_adj Shares Qty_adj Shares_adj Weight Weight_adj
TSLA -1 0.7 -0.0043 -0.0000 -100 100.0 0.0 -0.020 0.000
DIS -1 1.2 -0.0048 -0.0030 -800 300.0 -500.0 -0.042 -0.039
NFLX -1 1.7 -0.0048 -0.0036 -400 100.0 -300.0 -0.064 -0.071
QCOM -1 2.7 -0.0049 -0.0041 -1900 300.0 -1600.0 -0.082 -0.102
PG -1 4.5 -0.0063 -0.0057 -5500 500.0 -5000.0 -0.222 -0.299
MMM 1 0.1 -0.0049 -0.0000 1600 -1600.0 0.0 0.096 0.000
IBM 1 0.5 -0.0049 -0.0011 1800 -1400.0 400.0 0.079 0.026
UPS 1 0.9 -0.0048 -0.0031 1100 -400.0 700.0 0.069 0.065
BRK-B 1 1.7 -0.0049 -0.0039 2800 -600.0 2200.0 0.234 0.273
F 1 4.7 -0.0050 -0.0046 20800 -1800.0 19000.0 0.093 0.126

这与之前完全相同,尽管使用了两个不同的排序键。我们最初按照rRAR风险调整回报进行排序。现在,我们改为按rRisk_adj进行排序。那些没有贡献但仍然存在开放风险的头寸被减少了。在这一关键时刻,从这项练习中有两个重要的收获。

  • 在这个练习中,权重被减少了。它也可以增加。它可以在一边增加,在另一边减少。

  • 诚然,这是一项单调乏味的练习,没有特定的目标。然而,它有一个更加性感的绰号。一旦你打了个哈欠,带着你已经见过的胚胎资产配置方法的知识回顾一遍吧。

接下来,让我们看看这个-2%的风险减少如何影响所有主要变量:

print('Gross Exposure',gross,'Net Exposure',net,'Net Beta',net_Beta,'concentration',concentration)
gross_adj = round(abs(MV_adj).sum() / K,3) 
net_adj = round(MV_adj.sum()/abs(MV_adj).sum(),3)
net_Beta_adj = round((MV_adj* port['Beta']).sum()/abs(MV_adj).sum(),2)
net_pos_adj = port.loc[port['Shares_adj'] >0,'Shares_adj'].count()-port.loc[port['Shares_adj'] <0,'Shares_adj'].count()
print('Gross Exposure_adj',gross_adj,'Net Exposure_adj',net_adj,
      'Net Beta_adj',net_Beta_adj,'concentration adj',net_pos_adj)
rnet_adj = round(rMV_adj.sum()/abs(rMV_adj).sum(),3)
rnet_Beta_adj = round((rMV_adj* port['Beta']).sum()/abs(rMV_adj).sum(),2)
print('Gross Exposure_adj',gross_adj,'rNet Exposure_adj',rnet_adj,'rNet Beta_adj',rnet_Beta_adj) 

我们的输出如下,还添加了一些有用的评论:

# Before risk reduction
Gross Exposure 3.327 Net Exposure 0.141 Net Beta 0.24 concentration 0.0
# After risk reduction: absolute
Gross Exposure_adj 2.243 Net Exposure_adj -0.021 Net Beta_adj 0.13 concentration adj 0
# After risk reduction: relative
Gross Exposure_adj 2.243 rNet Exposure_adj -0.021 rNet Beta_adj 0.13 

仅仅将开放风险减少了 2%就将总暴露降低到了 3.327 至 2.243。净暴露从+0.141 变为-0.021。净贝塔从 0.24 降至 0.13。尽管净暴露基本中性,但调整后的投资组合仍然保持着多头。

在这种情况下,绝对和相对总数巧合地具有相同的值。正如你所见,只需稍微减少总暴露,就可以大幅减少总暴露,同时保持最健康的头寸。这是一个强大的练习,可以快速重新分配投资组合或策略的资源。

净暴露

净暴露是做多和做空头寸之间的百分比差异。净暴露是对市场方向性观点的*似反映:当为正时,看涨;为负时,看跌。净暴露对以下方面有直接影响:

  • 流动性 是最常被忽视但又至关重要的组成部分之一。做多和做空头寸具有相反的动态。为了保持净暴露低,做空头寸需要不断补充。与此同时,借贷的供应是有限的。这导致借贷成本增加。始终注意借贷利用率。不要让它超过约 66%。

  • 相关性:净暴露越低,相关性越低。例如,共同基金的相关性为 1,意味着它们模仿市场的波动。市场上涨,共同基金也上涨,反之亦然。

  • 波动性:净暴露对波动性的影响最大。净暴露越低,波动性越低。然而,以零净暴露为目标具有自身的系统风险。它在稳定的市场中表现良好,但在主要市场转变时可能极为痛苦,如牛市到熊市。

  • 绩效:净暴露越低,市场方向性对收益的影响就越小。

  • 收益率:做空者需要承担股息。低净暴露意味着做多端收到的股息被做空端支付的股息抵消了。这对做空端的股票选择产生了影响:高股息率的股票在做空端往往被低估。

在做多/做空业务中,每个人都熟悉净暴露的概念。认真对待他们的做多/做空任务的人会倾向于较低的暴露度,而机会主义者则更自由地摆动。因此,*均净暴露是重新分类做多/做空市场参与者的一种快速而粗略的方法。以下是一些参与者可能落入的广泛分类:

  • 超过+50%:这些是收取对冲基金费用的特殊情况的做多型基金。它们提供的不仅仅是下跌保护。它们不试图通过空头仓位对冲下跌。它们对空头头寸有着个别股票的看法。

  • 超过+30%:这些市场参与者通常被称为定向对冲基金。这是多空俱乐部中相对不太复杂的一群。他们通常是资产聚合者,假装知道他们在空头方面在做什么,但他们在想法产生部门往往遇到困难。他们的特点是高相关性,有限的上行参与度和零下行保护。他们是对冲基金的寿司传送带。当一个失败时,下一个色彩鲜艳的就会出现。

  • 净暴露度在-20%到+20%之间:最严肃的多空玩家在这个空间中运作。他们已经意识到,敞口控制和风险管理才是生意的关键。这种低净暴露度提供了低波动回报,但仍然受益于有限的市场定向性。

  • 净暴露度在-10%到+10%之间 是市场中性基金的领域。Alpha 严格来自股票选择和仓位规模。只有少数策略可以适应这种暴露水*。请记住,低净暴露度并不等同于低风险。这些基金的风险通常在尾部。难以始终限制敞口。这通常会以某些因素为代价。可以把它想象成是在重新收紧一根弹簧。在某些时候,被压抑的能量可能会释放出来并造成损害。

多空车辆应该在下行市场中表现出色,或者至少保护资本。在全球金融危机GFC)期间,它们没有做到铁打的营盘流水的效果。虽然它们在牛市中超过+50%甚至更多,但净敞口度很难降至+20%以下。尽管经理们可能宣称他们是熊市,但数字讲述了不同的故事。基金保持谨慎,但并非完全悲观。在+20%的净暴露度下,也许戴着拳击手套而不是赤手空拳,但仍然是同样的打击。

净暴露度可能是一个具有欺骗性的指标。低净暴露度不一定意味着低相关性。大多数市场参与者会采取几种手段来降低其净暴露度。最经典的技术是加大他们的少数空头赌注。集中度增加了波动性。另一种减少净暴露度的技术是卖出期货,其 beta 低于单个股票。这两种技术对相关性和波动性都有实质性影响。但是,净暴露度对于投资组合管理就像市盈率对于估值一样。这是一个足够好的快捷方式,但不应成为决策的唯一依据。最好将净暴露度与其他变量放在上下文中。因此,重要的是要超越净暴露度的头条数字,并通过净 beta 查看投资组合的构成。

净 beta

2005 年初,日本股市经历了一个史诗般的年份。感觉这一次不同。当日本当局决定逮捕乐天(JT:4753)的 CEO 兼新日本象征堀江财团时,派对戛然而止。高飞的小市值股票重新发现了牛顿物理学。

我们看好高飞的小市值股票,其业务模式奥妙,以及做空几个气喘吁吁的“结构性做空”以及指数期货。基金经理迅速对危机做出回应,通过卖出期货。尽管净头寸合理为+30%,但船正在迅速进水。作为自命不凡的风险管理者,我迅速提醒他,我们在贝塔、市值、交易所和流动性方面都有合成暴露。随着多头方面的小市值股票在 1.7 及以上,空头方面的令人痛苦的股票在 0.8,以及期货在空头方面为 1,我们的净贝塔值在 0.7 左右徘徊。正如一位投资者后来指出的那样,我们在上涨过程中的贝塔值为 1.5,在下跌过程中为 3。

贝塔是相对多空业务的核心概念。贝塔是对市场的敏感性。如果市场回报$1,贝塔为 1.5 的股票将回报$1.5。在数学术语中,这是股票收益与基准的斜率。净贝塔是调整后的多头和空头头寸之间的差异,以十进制值表示。它超越了净头寸的表面,以反映投资组合的基本方向敏感性。当风险存在且市场情绪良好时,高贝塔股票往往表现良好。市场奖励冒险者去冒更高风险的股票。流动性是任何市场的主要风险。因此,小市值股票的贝塔值高于大市值股票。高贝塔股票还是存在显着失败风险的行业,如科技或生物技术,或者存在资产负债表风险的金融行业。对对冲基金行业的批评者经常将对冲基金描述为贝塔交易商,或伪装成阿尔法的贝塔。批评者是正确的。相对多空投资组合在定义上是对贝塔的套利。同样,画家是一个把颜料抛向空白画布的人。

在牛市中,多头头寸的贝塔值将高于 1。空头头寸将由回报低于市场的股票组成,或者贝塔值低于 1。这可能导致净头寸在+20%左右,但净贝塔值牢固地在+0.5。表面上,净头寸可能看起来很低,但对市场的剩余敏感性可能会增加。在熊市中,多头头寸将由食品和公用事业等防御性股票构成,其贝塔值传统上低于 1。空头头寸将列出前一阶段所有领头的股票,它们正在排出它们的狂喜。这将导致净头寸在+5 至+20%之间,而净贝塔值在-0.1 至-0.5 之间。悲观的投资组合在多头方面拥有防御性股票,在空头方面拥有市场敏感性股票。

尽管净头寸暴露出的乐观态度明显,但负净 beta 表明了一种悲观的立场。在熊市中产生的负净头寸将产生 alpha,但会出现剧烈的波动。净 beta 是工具箱的一个重要组成部分。市场参与者本能地理解 beta 如何运作。稍加约束可以大幅提高*滑绩效。

接下来,让我们看看短期期货交易能带来什么。

卖出期货是做空的“垃圾食品”的三个原因

为了重申前一节中的声明,相对长/短期投资组合是对行业 beta 进行套利的。那些未能理解这一关键区别的不成熟市场参与者经常会卖出期货来减少其净头寸,而忽视了对净 beta 的影响。以下是卖出期货不是有效套期保值的三个原因。

卖出期货是对市值的一种押注

市场参与者经常会对做空端观点的稀缺性作出回应,通过卖出指数期货。

在多头方面,市场参与者喜欢通过寻找中小市值股票来展示他们的选股能力。这才是有趣和黄金机会所在。中小市值股票在牛市中的涨幅比蓝筹股更大。它们相对而言受到卖方分析师社区的覆盖较少。更容易接触到高管。找到几只涨了三倍或四倍的股票,一个新的选股传奇就诞生了。

与此同时,期货反映了指数的前几大市值。这使得做多中小市值股票/做空期货交易成为对市值的一种隐含押注。中小市值股票在牛市中表现优于大盘股,但在熊市中,市场对小型投机股票的态度并不那么友好。

卖出期货是对 beta 的一种押注

期货的 beta 值为 1。中小市值股票对市场的敏感性更高。它们是牛市中的跑马机,但在熊市中表现糟糕。当市场暴跌时,中小市值股票的跌幅比大型、沉闷的蓝筹股更快。在牛市中,做多中小市值股票/做空期货市场会拖累绩效,但在动荡的市场中不提供下跌保护。

对 beta 进行套期保值的唯一方法是采取深度净做空方法。

由于通过期货“套期保值”的市场参与者不太可能在首次进行做空操作时感到舒适,因此他们可能在牛市和熊市中始终保持净 beta 正值,或者通过做多股市获得收益。具有讽刺意味的是,对股票卖出期货在市场基准上实现超额收益。只有在该资产类别预计会在市场上实现超额收益时,这种策略才有效。对这种策略的不太光彩的描述称为beta 驯马手

卖出期货是一种昂贵的懒惰形式

许多机构投资者已经通过期权和期货对互惠基金中的风险进行了对冲。他们已经有了对冲他们的多头注资的复杂性。他们不需要额外支付一群游客 2%和 20%的费用来做他们自己能做的事情。归根结底,卖出期货表明了不负责任的业余精神,这是投资者自全球金融危机以来已经敏锐意识到的事情。

如果你曾经想知道为什么即使在熊市阶段,尽管净暴露度低,你的业绩仍然不佳,净 beta 可能是罪魁祸首。如果目标是提供低相关性回报,那么较低的净 beta 就是起点。

集中度

集中度是指投资组合中的股票数量。净集中度是多头头寸减去空头头寸的差额,可以用总头寸的百分比或绝对值表示。

集中度直接影响:

  • 流动性:建立和清算头寸会对市场产生影响。

  • 波动性:如果目标是提供低波动性回报,那么集中度就是起点。名字的数量越多,波动性就越低。

  • 表现:大规模的集中投注能够取得巨大成功。小额投注能够积累收益。

集中度通常被认为是一种投资风格的属性,因此没有得到应有的关注。这有点像大蒜——一种美味的调味品,在初次约会时不建议使用,但也是一种抗癌的超级食物和吸血鬼驱赶剂。

一些市场参与者认为,实现卓越表现的关键是在几个高信心大投注中取得成功。这可能是一种成功的策略,但这不是重点。表现最佳的产品不是最畅销的产品。跑车吸引的客户有限。

当涉及到资产配置时,投资者将大部分资产分配给低波动性的投资策略。他们出于一个简单的原因交易回报以换取稳定性。机构需要与明确的负债(如养老金支出)匹配合理可预测的资产。然后,他们将用较高波动性产品的小额分配提高回报。所以,对于任何经理来说,真正的问题是:你要针对哪一笔资金?你想游泳在低波动性产品的奥运规模的游泳池中,还是在可支配的赌博资金的小型游泳池中?

接下来,我们将挑战一些关于集中度的老生常谈。

人类的局限性

市场参与者经常认为,他们能够管理的股票数量存在自然的人类限制。超过一定数量的头寸,一切都变得模糊。他们跟不上信息流并做出及时决策。

这是一个投资组合管理系统问题。数据没有以一种有助于经理做出交易决策的方式结构化和可视化。我们将在第十三章投资组合管理系统中讨论这个问题。

保值不是令牌

一些市场参与者进行少数大赌注,并保留一长串探索性的小仓位,称为对冲。一些奇特的对冲包括对商品的敏感性:中国、黄金、利率等。这些仓位通常太小,无法在个体基础上实质性地对冲风险,但总体上很重要。因此,它们是示范性的例子,允许市场参与者说他们已经对冲了他们的投资组合,抵御了外部风险。

长尾策略是小中市值长/短领域的经典。再次强调,这是一个投资组合管理系统问题,而不是风险管理策略。

低波动收益的悖论:结构性的负净集中度

可持续吸引和留住投资者的方法是在短侧比长侧结构性地拥有更多的名称,或者净负集中度。投资组合上通常长侧的名称比短侧多。当面对短侧想法的稀缺性时,市场参与者会倾向于放大其空头赌注以降低净暴露。他们最终通过称其超大头寸为“高信心空头”、“结构性空头”或“策略性空头”来合理化这些决定。

问题在于大量集中的赌注增加了波动性。由于空头一方的波动性极高,这导致了整个投资组合的波动性。现在,投资者希望波动性低。降低波动性的唯一方法是减少短侧的集中度。这意味着更小的赌注和更多样化的名称。正如我们在第五章中所看到的制度定义,这在相对长/短期投资组合中是可行的,但在绝对长/短期投资组合中要实现这一点要困难得多。空头一方需要比多头一方结构性地拥有更多的名称来补偿波动性。

关于集中度的实用提示

集中是三个变量的函数:*均名称数量、大赌注与小赌注的比率和交易成本。

*均名称数量

一个健康的投资组合在每一侧应该有 30 到 60 个名称。没有任何一个头寸过大以至于能够摧毁业绩,但足够大以在实质上做出贡献。此外,头寸数量仍然是可以管理的。

大赌注与小赌注的比率

第二个因素是大赌注与小赌注的比率。Fidelity 波士顿的一项内部研究测量了管理人员投资组合中最大头寸与最小头寸的比率、超额收益以及最终资产管理规模的保留情况。结果是一清二楚的:

  • 大赌注与小赌注的比率越高,波动性越高。大量集中的赌注推动业绩,但缺点是收益波动率升高。这是投资者的一个巨大障碍。他们喜欢收益,但无法向老板证明波动性。

  • 持仓管理比率低于 2.5 的经理与大赌注差距较大的经理相比,跟踪误差显著较低。他们的最大赌注不会大到足以推动其整个投资组合的波动性。低跟踪误差与资产管理规模的稳定性相关。用执行交易员的话说,这意味着当事情顺利时,你会被称为“股票选手”,但当你的风格不受青睐时,你会被归类为高跟踪误差风险。这相当于机构投资者的“没有人因为买 AAPL 而被解雇”。

大赢家将在买方扩大,在卖方收缩。在买方,赢家不应该使整个投资组合变得微不足道。相反,在卖方,它们不应该被允许消失。

维持一个健康、动态的投资组合的一个简单方法是追踪前 10 项的总权重与后 10 项的总权重之比。比率越高,集中度越高,因此波动性越大。将这个比率保持在 3 以下可以确保投资组合中既没有过大的赌注,也没有过小的仓位。

保持你的粉末干燥

最后,这是一个简单而强大的来自卖方的小贴士:拒绝小仓位。这在卖方是普遍存在的。在买方,即使是 0.50%的小赌注也可以变成强大的仓位。回到 1997 年 8 月,比尔·盖茨以 12 美元的价格购买了一家名为 AAPL 的垂死的便士股票的 200 万美元股权。然而,在卖方,成功的交易会缩水。即使一只股票下跌了 10%,-0.50%的初始赌注也只会回报+0.05%。加上交易成本和滑点,剩下的钱勉强够喝咖啡和吃可颂了。在卖方,保持干粉直到有机会。市场参与者经常因为害怕卖空而害怕。他们会采取太小以至于无法伤害但也太微不足道以至于无法做出贡献的仓位。因此,首先要做好风险管理,然后执行你的策略。这是一些与说这句话的绝地大师一样古老的建议:“要么做,要么不做,没有尝试。”

其他暴露

一些市场参与者喜欢追踪其他对冲,比如行业或部门风险,或者交易所和因子风险。

行业暴露

保持多元化的行业暴露是一个良好的做法。通常情况下,你不希望你整个长/短期部门的暴露看起来像是 1999 年技术长,2000 年技术短的情况。一些市场参与者喜欢完全对冲他们的行业暴露以减轻行业风险。这引入了另一层不必要的复杂性。在实践中,整个行业主导或落后于市场。一个例子是:在 2008 年,很难找到任何金融部门的股票属于买方。

只有在成对交易或套利策略中才适用行业中性。同一行业中的所有股票并不以相同的速度行进。行业中性引入了一个有趣的资本配置问题:应该反映底层行业的市值还是成分之间的差异?前一种分配将 passively 沿着广泛市场移动。行业的市值和暴露将被匹配。它会看起来是低风险的,但不能保证有吸引人的回报。相反,高的同一行业差异提供了更多捕捉阿尔法的机会,但偏离了行业市值。

只有在获胜者和失败者之间的同一行业差异明确定义时,行业中性才能产生阿尔法。科技行业是一个很好的例子,例如,看好 Facebook/空头 Twitter。

交易所曝光

谁提出“理性投资者”概念的人显然从未在狂欢的牛市中踏上交易大厅。获胜效应正在全力进行。睾丸酮在冷静,理性,自私的经济代理人身上疯狂地泵动,又被称为“股票投机者”。昨天高度投机的问题被封为“新的投资范式”。后向理性化唱着同样的老调: “这一次不同!”

这样的暴发户问题很少在古老的主要交易所上找到。它们在美国的纳斯达克,日本的 JASDAQ,韩国的 KOSDAQ 等上市。

在牛市期间,一个经典的策略是看好投机股票,空头蓝筹股。然而,这是单向行进的。反之效果不是那么好。看好蓝筹股并空头投机是一种难以在实践中执行的策略。在超过最大市值之后,借贷变得困难,流动性蒸发,买卖价差巨大。

流动性是熊市的货币。当市场动荡时,应坚持交易所主流的流动性资产。

因素曝光

2007 年量化基金的灾难清楚地证明了空头方面有着自己的动态,并且值得有其特有的因素。我们都会因为学者们的聪明才智而从进一步研究空头交易中受益良多。但是,由于关于最佳投资组合构建的讨论似乎在 70 年前现代投资组合理论(MPT)的前披头士时代达到了一个“永久性高原”,学者们没有太大的动力提出适用于空头方面的因素。

理论上,因素是有意义的。在回测的临床环境中,因素也表现良好。然而,在实践中,空头方面并非是分子烹饪的练习。AMZN 不是一系列因素。它是一家公司,一支股票和一个故事。

管理多头/空头投资组合比传统的仅多头投资组合更具创造力。它也会引发复杂性。因此,坐下来从头开始设计投资组合管理指南是明智而有趣的。我们将在本章的剩余部分进行介绍。

设计你自己的授权

"人们会按照他们写下的去生活,"

– 罗伯特·西奥迪尼

金融是时尚行业中唯一一部分,去年的款式仍然畅销。资金毫不费力地流向去年的佼佼者。每个人或多或少都在做着同样的事情:基本面分析、公司访问、收益模型、技术分析。很难提出一个与众不同的理念。如果你想在潜在客户心中留下持久的印象,向他们展示他们很少看到的东西:一个经过记录的流程。他们可能选择今天不投资,但他们会记住你。

投资者喜欢将经理人归类。他们已经有了一定数量的类别。如果你不适合任何一个类别,他们可能不会为你新建一个,除非表现迫使他们这么做。因此,让他们的工作变得容易:告诉他们哪个类别最适合你。对外界而言,你的授权是你的身份。你越是完善它,你在投资者眼中就显得越可信。你将不再是 "下一个 [在此处插入最新的幸运股票选手的名字...]",吹嘘自己的出色股票选择能力。你将成为一个有远见并有过程可依的人。没有什么比一个审慎的资金管理者更具吸引力,他能理解风险并进行计算的押注。

很少有市场参与者花时间明确规范其流程。坚持计划的最有效方法是将其写下来并对自己负责。如果你的目标没有明确规范,一切都将停留在空想中。以下是一种逐步方法,将帮助你澄清你的流程。首先,我们将从信号模块开始。其次,我们将进行头寸大小确定。第三,我们将添加敞口和风险管理。最后,我们将考虑你的目标。我们将用一系列问题探讨每个主题。

请准备好笔记本和你的交易日志。

第一步:策略规范化

"Persona 是拉丁文,意为演员戴的面具。"

– 约瑟夫·坎贝尔

从你的策略概要开始。用 2-3 句话写下你的电梯演讲。这是你要求投资者将你放入的框架。如果你现在没有一个明确的想法也不要担心。当你完成这个过程时,这个框架会显露出来。

三分之二的车祸后住院的人仍然会自认为是高于*均水*的司机。我们认为我们是谁,我们内心深处的批评者对我们喊叫的是谁,我们公开声称自己是谁,以及我们做什么,都生活在一个同步的*行多元宇宙中。

我们不会走传统的成长对价值,基本面对量化,等等的路线。这不是一次营销行动。你不是在试图筹集资金。我们试图恢复你的个人所有方面的内在对齐。我们将会将你的策略形式化到可以被编程的地步。

信号模块

将你的表现与你操作的基准进行比较。你擅长哪些市场?更重要的是,你不擅长哪些市场?它们是向上趋势,向下趋势还是横向趋势?它们是否波动?你是在市场之前还是之后达到高峰?你是在市场之前还是之后复苏?你的表现是比市场更快还是更慢下跌和恢复?

计算短期滚动夏普比率,或者韧性指数。关注于它下跌和恢复的时刻。我们的目标是让你在连败时期变得坚韧。对于以下一组问题,请参考你的交易日志或者交易记录。不要将非标准行为标记为好或者坏。

列出按策略的所有入场类型,包括机会主义交易:

  • 你的季度和年度滚动交易边缘分别是多少?下次有人问起你的交易边缘时,这些数字应该信手拈来。此外,这将听起来比对你独特的分析能力的模糊论文更加令人印象深刻。

  • 你每一方的经典入场信号是什么?走得比一般的想法再远一步。翻阅你的交易日志。是什么在过去 50 次交易中导致你在每个仓位上那个特定时间动手的?如果你没有一个具体的原因,也写下来。

  • 你多久进行一次机会主义交易?有时我们会从自动驾驶模式切换到手动模式。我们都会遇到不遵守我们标准规则的机会主义交易。例如,可能会出现一些坏消息导致股票暴跌。机会主义交易在投资组合中有一席之地。然而,当它们频繁或者占比重时,就会对结构和纪律产生合理的担忧。神圣的行业术语是“风格漂移”,这应该是一个主要的警告信号。

  • 当你的策略不起作用时,你的交易频率会发生什么变化?你会交易更多还是更少?例如,是否会在完全停止交易之前经历虚假的正信号?比较连败开始时和结束时的入场数量。可能存在一些交易疲劳。你会放弃信号,因为你相信它们再次会是虚假的正信号。

  • 你会分批进入吗?两边都是吗?你会进行多少次入场?回顾你的交易日志,并明确规则是什么促使你动手。是否有特殊情况?有交易你选择不分批进入的吗?

  • 在符合入场标准的情况下,你放弃了哪些交易?不交易也是一种投资决策。从不进入的决定来看我们的交易选择,为你对系统的信任提供了有价值的视角。导致你拒绝这些信号的背景是什么?

  • 如果你经常放弃交易,开始记录那些被拒绝的交易。还注意为什么拒绝它们的原因。

接下来,专注于你的退出,认真审视镜子里的自己:

  • 你的止损规则是什么?在过去的 50 次交易中,你违反了止损规则多少次?在触发止损前是否关闭交易?规则是什么?你有多少次以百分比点数的形式覆盖了规则?

  • 你使用移动止损吗?规则是什么?你的移动止损规则是否根据连胜/连败而变化。

  • 你如何重设止损?

  • 你会逐步减仓吗(减少头寸)?

  • 你有时间退出策略吗?多少个周期?是否也适用于嵌入 P&L 的老头寸?你是否拖延时间退出?

  • 你的有利退出策略是什么?在过去的 50 次交易中,你偏离了多少次?

  • 在双方都有的情况下,你的滚动假阳性率是多少?如有疑问,请使用你的击球率。专注于回撤。在连续亏损期间,你是否扩大或缩小止损?

  • 你会反向交易吗:从做多转为做空,反之亦然?

  • 交易的模式是:亏损还是盈利?你是趋势跟随者,还是使用均值回归策略?

你真的做了功课还是仅仅是智力上回答了问题?好吧,然后回答这个:说出三个你的行动与你的信念不符的领域。在过去的 50 次交易中,最大连续止损次数是多少?与基准的相关性是多少?如果市场在接下来的 6 个月内保持横向,转为熊市或转为牛市会发生什么?一年中有多少个月你会处于亏损状态?

记住,当涉及测试系统的健壮性时,批评是一种健康的实践。站在你和系统成功之间的是你的自我。你可能会得出这样的结论:你的无懈可击的交易系统的结构完整性像瑞士奶酪一样。没必要责备自己。没有人生来就是黑带。这既不好也不坏。我们都必须度过那个阶段。这只是一个调整你引擎的邀请。

接下来,利用上述问题的答案绘制你策略的流程图。互联网上有许多免费的网站。

  • 从经典的入场/退出案例开始

  • 添加逐步加仓/逐步减仓

  • 添加止损

  • 添加最终退出

  • 重复上述过程,带入特殊情况的入场

流程图是构建策略的强大工具。它们迫使我们进行逻辑思考。用条目和退出的顺序建立你的策略模板。然后填写触发这些事件的条件。实际上,所有的策略都可以归结为几个模板。它们从最简单的沃伦·巴菲特模板开始:买入后不做任何事情,一直到长/短期逆转的逐步退出/逐步进入。策略就像搭积木一样。当你努力优化你的交易优势时,你可以添加或减少积木。

记住,你在与严谨的人竞争,他们认真对待这个过程。你在澄清你的过程中迈出的每一步都会让你与那些不这样做的人区别开来。你的策略流程图是绝望时的一盏明灯,是狂喜时的理性之声。不要忽视这一部分。你认为有多少市场参与者会花时间澄清他们的策略?投资者可能只能用一只手数出能够制作出信号引擎流程图的经理的数量。他们今天可能不会和你一起投资,但他们会记住你的专业精神。

现在我们已经把引擎拆开了,让我们来看看变速器。

资金管理模块

这个模块包括头寸规模管理,应该考虑在我们本章中看到的市场变量的背景下:

  • 你的头寸调整算法是什么?

  • 它在你赢或输了一连串的比赛时会发生什么变化?在赢了或输了一连串比赛之后,它是什么样子?

  • 对于你的风格,还有哪些其他位置大小调整算法更合适?

  • 你每边有多少个名字?你的表现周期如何演变?

  • 你的大/小头寸比是多少?

  • 将你的敞口与市场进行对比:总敞口、净敞口、净 beta、投资组合热度、集中度、净交易(买入与卖出占总敞口的百分比)和表现。

  • 在输掉一连串比赛时,你的敞口是什么样子?具体一点。

这是你在市场上的存在的传输部分。你的引擎在厚厚的市场中发出信号。市场向你扔东西。你的头寸大小、集中度和敞口管理决定了你选择如何应对。绘制那些数据。"你是谁?"图表是你将要建立的最重要的视觉工具。在一个图表上绘制以下元素:累积基准和策略收益、总敞口、净敞口、净 beta 和净交易(买入减卖出占总敞口的百分比)。那张图表将展示市场向你抛出的东西,以及你如何通过交易净买入/卖出、总体信心和净和净 beta 的方向性来应对。很少有数据可视化练习有这样的"哇"效果。

步骤 2:投资目标

新手对冲基金经理总是说他们想尽可能赚取更多的钱。老手想尽可能稳定地赚钱。有老交易员也有大胆的交易员。但没有老的大胆的交易员。追求回报或一致性是互相排斥的。老手只是简单地经受住了最初的自负,接受了自己的本性和能够取得的成就。

许多交易教练都会鼓励你在开始交易之前定义你的目标。他们会逼迫你去做一些你不是的事情。要么你征服自己,变成那些目标,要么你反抗,最终会交易其他完全不同的东西。人类在实现理想愿景方面表现糟糕。每个其他的多空玩家都说他们的目标是每年 15-20%的低相关回报。但现实是只有少数精英能够持续实现两位数的回报率。每个人都希望在 1 月 1 日拥有六块腹肌,但从三月开始健身房就空了。这个过程旨在从你的信念到你的行动中产生一致性。赚钱只是将内在信念从你的潜意识带到你的意识,再一直延伸到你的无意识习惯的过程。市场巫师并不比别人聪明,他们只是有着更聪明的交易习惯。

现在,你知道自己身在何处。你也知道自己想要去哪里。为了实现这一点,你知道需要发生哪些变化。你也对什么可以做什么不可以做有一个现实的看法。目标并非玄学般的愿望。你的目标可能很高远。但它们仍然扎根于现实。下一步是将你的目标具体化为一个投资组合管理过程。回到传输部分,关注变量。你的头寸大小算法是什么?使用你工具箱中的四个主要暴露来定义你的投资组合:总量、净量、净β、集中度。这些将决定相关性、波动率、回撤,并最终影响表现。

考虑到数据和条件路径的多维数组,这个练习很难模拟。例如,有些策略一年只有几次交易。如果你因为手头现金不足而错过了一次交易,而这个交易后来的表现比其他证券要好出 20%,你的整体结果就会被扭曲。这个问题没有简单的解决方法。这些回测问题超出了本书的即时范围。

第四步:设计你自己的任务:产品、市场、匹配

多空头像其他任何产品一样受供需法则的约束。多空投资组合就像牙膏或肥皂等其他商品产品一样。在没有销售发生之前,什么都不会发生。你的工作就是让那块肥皂变得不可抗拒。

一旦你明确了你的投资目标,那么就是进行现实检验的时候了。你的目标是否可实现?到现在为止,你应该对自己能适应的范围有个合理的了解。例如,你可能明白,在净暴露度在+/-5%、总暴露度在 200%的情况下,+30%的回报是非常不可能的。你也知道,将波动性减半将使你排队等候的时间缩短。

你的产品是否受欢迎?请记住,投资者宁愿把资金投入每个月回报 0.5%的产品,也不愿把资金投入每年有 9 个月处于亏损状态的产品,即使后者的回报率为+20%。

这是你考虑“产品、市场、适合度”过程的步骤。你的风格可能不完全符合市场需求,但只要你愿意做出调整,你仍然可能拥有一个有吸引力的产品。好消息是,你将与那些心态是“建造它,他们会来”的人竞争。

第五步:记录

每个市场参与者都遭受交易选择性遗忘的困扰。不幸的是,大多数市场参与者花费大量时间开发交易系统,却最终交易其他东西……每次我们放弃一个交易、超过止损、增加赌注,我们都在交易与我们原始系统不同的东西。

除非我们将我们的交易历史纳入我们当前的交易决策中,否则我们注定要重复同样的错误。像西西弗斯一样,我们将举起我们表现的巨石,只是看着它们在下一个故障时滚下来。

我们防止进一步损害的两种主要方式是通过头寸规模和拒绝交易。例如,我们都有自己的宿敌股票,我们尝试了多次都失败了。与其冒着第二次风险相同的金额,不如冒着更小的风险。海龟交易员有一个规则:经过 3 次失败后就停止尝试。

记录所有交易,按策略、方向和证券分类。例如,它可能是 ABC 股票,长期趋势跟踪。这样,你就能够计算出按策略、方向和股票分类的统计数据,如盈利预期和命中率。

这些统计数据对评估你的系统很有用。你的交易日志只能提供你是否遵循交易系统的不完整视图。除了你的交易历史,还有四个领域可以直接衡量你的遵循程度:进场、出场、头寸规模和记账。所有这些都与交易心理有关。

进场

除了你进入的交易,还要跟踪你放弃的交易。正如克劳德·德彪西所说:“音乐也是音符之间的沉默。”你没有选择的交易与你选择的交易一样定义了你。放弃一个否则有效的交易也是一种交易决策。它对你的投资风格有不同的看法。市场参与者放弃进场的原因大致有四个:

  1. 现金余额不足:这仍然是错过信号的头号原因。

  2. 对系统的不信任: 这是一种根深蒂固的失败和不足的恐惧。解决方法是有良好的统计数据并多做工作。

  3. 系统不完整:有些系统并不适用于尾部事件。在不稳定的环境中进行交易可能会危及业绩。

  4. 不处于正确的心态: 这是那种在深度连续亏损期间放弃免费钱的经典被击倒的交易员。这个问题有一个简单的解决方案:进行小额交易。

作为最后的警告,何时不进入头寸,一个对冲基金经理曾在品酒之后坦白承认,他的一个逆向交易是出于报复。他曾经通过交易将其视为多头,现在他正在通过做空报复他自己(以及他的投资者)。

退出

你会以某种方式退出交易。这将反映在你的交易日志中。可能并不立即显而易见的是,你在关闭头寸时是否遵循了你的系统。

特别注意止损。每次强行设置止损或过早获利时都要计数+ = 1。有时这可能是正确的决定,但这是偏离你的系统。每当你违背你的系统时,评估你的心态。

头寸大小

一个没有记录情绪的交易日志就像一部没有声音的电影。我们交易的是我们的情绪。这既体现在过度/不足的交易上,也体现在头寸大小上。兴奋的交易员过度交易并超大头寸。处于低迷状态的交易员错过了“免费钱”交易,并过于保守地下注。你必须努力像精神病患者一样交易,尽量减少情绪干扰。

跟踪你的情绪很简单。根据你的主观情绪稳定程度进行评分,从沮丧(-3),到每次交易进出时的*静的圣洁空间(0),再到统计上受挑战的 200%(过度)自信(+3)。几次进入后,就会有一个基准线。我在读范·萨普博士的时候发现了这个有趣的游戏。我个人发现无聊与对系统的遵循呈正相关。显然无聊是好事!

记录

反思和记录是将批判性眼光带入你的流程的有效技术。这将为你的工作带来创造力和客观性。记录并不是一种自由自在的自我责备练习。当情绪极端时,市场参与者常常口若悬河,但当事情进展顺利时却保持沉默。将你的日志结构化为四个部分:

  • 语境:强调你在市场上所见的。这为你的交易决策提供了背景。也许你没有买入是因为那时世界看起来似乎快要结束了。

  • 你的立场:这需要具体。养成给你的观点附加数字的习惯。例如,我的总收益率是 180%,高于 200%的*均水*,我的净β比一个月前高了+0.1。我持谨慎乐观态度。风险管理是一种语言。

  • 策略改进:什么有效,什么无效。这是有趣的部分。

  • 投资理念Evernote 是一款优秀的日记软件。使用标签和笔记本来分类你的日记。

单单那种记录的纪律就足以让你脱颖而出,与股票投机者的无名熔岩区别开来。并不是每个投资者都会和你一起投资,但每个人都会记得你的记录纪律。

步骤 5:完善你的授权

“纪律就是做你讨厌的事情,像你热爱它一样。”

– 迈克·泰森

这是一个迭代过程。花时间制定出一些你感觉舒服交易的东西,这将吸引投资者。上述过程是应用于股票市场的“刻意练习”。详细阐述你的流程将迫使你专注于策略的具体点。你的记录将提供即时反馈。这将提高信心,并将你与竞争对手区分开来。

总结

管理一个多空组合就像从家庭 SUV 升级到跑车一样。没有适当的训练,人们往往会将他们闪亮的新玩具带到越野赛道上。在这一章中,我们看了一下操纵你所需要吸引你想要的客户的回报的主要杠杆。这些是总曝光或杠杆、投资组合热度或开放风险、净暴露或方向性、净 beta 或对市场的剩余敏感性以及集中度或投资组合中名称的净数量。这些变量提供了对波动性、表现、相关性和流动性的访问,就像市场影响一样。

在接下来的章节中,我们将带你逐步了解如何构建一款股票多空产品的方法。我们将使用一种强大的技术将股票重新分类为看涨、看跌和横盘市场。从那里开始,我们将讨论执行:进场、出场、订单优先级。我们将以一个最被低估的工具,即投资组合管理系统,结束。但首先,让我们从一个主要的障碍开始:观点的稀缺。这种方法将使您能够在整个市场之前定位自己,并使您看起来像一个卖空大师。

第十二章:信号与执行

“我们有两只耳朵和一张嘴,这样我们可以听两次比说话多”,

– 司提反

这一章将告诉您如何准确地设置订单优先级及其背后的原因。我们将研究如何使用相对序列管理投资组合,但在绝对序列中执行。我们将深入研究出场,从不盈利和盈利的情况开始。我们将考虑出场的心理卫生。然后,我们将转向一个热门话题:进入和重新进入。我们将提出直觉上反直觉但有效的低风险高回报的进入技巧。整本书都铺垫到了这一点和接下来的章节,所以我们将重新讨论书中的部分内容,提出一些综合我们迄今所见的一切的代码,并可视化结果。

在此过程中,我们将讨论以下主题:

  • 导入库

  • 时间就是金钱:订单时间的重要性

  • 订单优先级

  • 出口

  • 进入

您可以通过以下链接访问本章中所有图像的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。您还可以通过该书的 GitHub 存储库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

对于本章和本书的其余部分,我们将使用pandasnumpyyfinancematplotlib库。我们还将使用 ScientificPython 库中的find_peaks。所以,请记得首先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt
from scipy.signal import find_peaks 

时间就是金钱:订单时间的重要性

2005 年,日本市场经历了指数上涨。僵尸股再次复活了!2006 年 1 月底,警方实际上突袭了这个派对。他们逮捕了这个新日本典范的标志性人物。突然间,感觉就像是一个夜总会关门了。粗糙的霓虹灯突然间被打开。醉醺醺的人们在舞池里相互凝视,困惑不解。现实带着报复性回来了。漂浮的僵尸重新发现了牛顿物理学。不幸的是,对于任何单一问题的借贷的可用性和成本都是令人望而却步的,所以在我和美林证券股票借贷部门的伙伴们一起,我们想出了一个信用评级资产价格CRAP)篮子交换的想法。我们倾入了所有我们能找到的僵尸。借贷成本是可以负担得起的 2%。价格将是当天收盘价。容量几乎是无限的。在复合 beta 达到 2.3 时,它比指数期货具有更大的扭矩。我们已经做好了生意。

但是当是时候下手时,负责人犹豫了。他抱怨说太波动了,太有风险了,太不正统了。因此,我们最终选择了“监视”它,一个花哨的词来制造《大富翁》的货币:-2%,-4%,-5%,日复一日。但他对这笔交易仍然不感到舒适。三周后,我得出结论:异国情调是一个度假胜地,而不是一个价值三亿美元的组合投资组合中的做空位置。然后,有一天,掉期进来了。我的名字也在上面。那天晚上我睡不着。第二天,它又额外跌了-2%。第三天,它再跌了-0.5%,但然后,它开始稳定下来。它上涨了+0.5%,+3%,+6%。我们完美地把握住了底部。但现在,史上最大的做空追击正在给做空者带来民主。最终,我们以巨额亏损*仓了一笔在不到两个月内下跌了-63%的做空仪器。

故事的寓意:时间就是金钱。有正确的想法是一回事。良好地执行它是另一回事。熊市反弹定期发生。生活中有三个确定性:税收、死亡,以及在二者之间,熊市反弹。一些市场参与者声称市场无法进行时机把握。在多头方面,市场更加宽容。构思和执行可以融合在一起。支持多头的上升漂移也惩罚了空头卖家。许多基本面空头卖家经常抱怨他们太早或有时太晚了。

订单优先级

进入是一个选择,退出是一个必要性。你可能随心所欲地进入,但你很少有机会按自己的意愿退出。在执行交易员的英语中,进入是限价单,而退出是止损单或市价单。长期持有者经常苦恼于现金余额。他们需要知道每天可以购买多少。长/短组合投资组合比传统的仅长仓簿记有更多的变动部分。事情很快就会变得混乱不堪。因此,为进入和退出设置“通行权”是明智的选择。在执行交易员的英语中,退出始终排在第一位。消耗现金的订单具有“通行权”。这可以总结如下:

  1. 买入做空是最高优先级。它的功能类似于买单。它消耗现金。做空对长期购买力和总体敞口产生影响。买入做空在极少数情况下可能触发保证金调用。

  2. 卖空是次高优先级。它释放了被困住的现金。

  3. 卖空:做空生成多余的现金。这些多余的现金可以用来购买更多的股票。一些司法管辖区要求做空者在下达做空订单之前先获得股票借出。未能这样做会导致裸卖空。这种做法指的是未事先找到借出就进行卖空。这本身并不违法,但严重不受欢迎。交易通常被重新分类为“未交付”,并进行关闭。如果你想被认真对待,就不要...

  4. 买入多单:再次强调,最重要的交易是最后进行的。只有当所有交易都排好队之后,才应该进行买入多单的订单。如果空头头寸没有*仓,但进入了多头头寸,这将减少现金余额。如果需要急忙*仓空头头寸,这可能会带来一些风险。

让我们回顾一下。首先是降低风险的交易。这些交易包括买入*仓和卖出多单。然后是旨在增加现金余额的交易:卖出空单和买入多单。

重新进入信号是一个案例,其中重复犯罪者应该被安排在前排。任何重新进入信号都是更长期趋势仍然有效的确认。此外,先前头寸已经嵌入了损益。因此,综合未*仓风险低于任何新进入的风险。然而,这也有局限性。增加已有头寸的操作被称为金字塔加码。就像生活中的一切一样,趋势会成熟。每个新头寸都会更接*趋势的成熟——最终是耗尽。这增加了集中风险和波动性。因此,通过例如每次重新进入时采取更小的头寸来降低风险是明智的。头寸规模最终会变得太小而被拒绝。

接下来,我们将更详细地看一下当我们以相对系列运行系统时会发生什么。

相对价格和绝对执行

虽然你的系统是基于货币调整和基准相对价格运行的,但是以美元发送一笔关于日本股票相对于 MSCI World 的订单,确实会引起交易台上一些滑稽的表情。这对你来说可能是昭然若揭的,但需要说明的是,交易员不擅长心灵读取。在现实世界中进行交流时,订单必须以本地货币进行下达。

由于系统是基于货币调整和基准相对价格运行的,所以止损不需要被翻译。实际上,止损与本地绝对价格无关。在前面的章节中,止损是基于相对价格而不是绝对价格的。这是因为你的系统应该是基于相对价格的。这意味着止损订单不需要在经纪人的服务器上停留。不需要挂止损订单的一个好处是它们不能被掠夺性的智能资金(高频交易HFT)参与者)操纵。

订单类型

高频交易的出现严重丰富了交易订单的选项。想要优化执行超出击败成交量加权*均价格的市场参与者,欢迎探索订单执行的广阔领域。

为了本书的目的,让我们坚持一个简单的原则:入场是一个选择,退出是一个必要条件。这意味着退出交易要么是市场、止损或止损限价订单。入场要么是成交或取消,限价或止损限价订单。当我们扳动扳机时,我们希望成交。我们内心的白痴喜欢追逐,但我们的业绩记录讨厌糟糕的执行。你的入场和退出缺乏纪律将影响你的业绩记录,所以坚持计划。一点点克制会有回报。从相对系列到绝对系列的转换中会有一些小的滑点,但最终这一切都会*衡起来。

接下来,让我们讨论退出和入场——我们按照这个顺序讨论它们,因为如我们已经注意到的,退出应优先于入场。

退出

退出分为不盈利和盈利退出。前者旨在生存,而后者则建立繁荣。我们在第二部分外在游戏:打造强大的交易边缘中大量讨论了退出。以下是一个逐步简短的概括,涵盖了退出的实际方面和心理卫生。

止损

止损对交易边缘公式中的四个变量中的三个直接可测量影响:胜率、败率和*均损失。仅因为这个原因,它总是位于优先级列表的顶部。记住,将专业空头卖家与游客区分开来的是设定止损并遵守它们的能力。接下来的内容可以视为一个重要的核查表。我们在整本书中都涵盖了这些话题,特别强调了第七章提高您的交易边缘

  1. 在逻辑上的表达位置设置止损,其中论点被无效化

  2. 设置一个损失缓和的跟踪止损:这有两个积极的影响:

    • 它可以减少损失,并将盈利期望倾向于保本。

    • 在心理上更容易处理和停止较小的持仓

  3. 持仓规模:在发送交易之前运行风险管理以计算您的暴露。

    • 保守地设置固定止损

    • 在跟踪止损上积极一点

接下来是心理准备。小额损失会消耗你的情感资本。不要忽视你的心理卫生。提醒一下,所有优秀的交易者都专注于心理资本,而*庸的人则担心移动*均持续时间或其他毫无意义的琐事。

事前评估

想象自己在亏损时关闭交易,并感受相关的负面情绪。重复这个过程并调整大小,直到你感到舒适接受损失。这样可以提前处理你的悲伤。按下发送按钮,对你的资金说再见,并考虑以下因素:

  1. 时间停止:削减或减少持仓规模。时间停止在心理上很难执行:“如果我再给它多一天、一周、一个月……”一个技巧是想象一个真实的时间浪费者,并将图像锚定到持仓位置。

  2. 减少损失:冥想,保持警觉。这可以防止急切或恐惧。损失是游戏的一部分。

  3. 止损:这是最坏的情况。如果您在事前作业上做了功课,这应该是个形式上的事情。首先,原谅自己。

事前评估可追溯到斯多哥哲学家和罗马皇帝马库斯·奥里利乌斯。这是最有效的视觉化练习之一,可以在压力下保持冷静。

齐格尼克效应

提醒自己以下内容:

  1. 一旦头寸消失在视线之外,您将在 2 周内几乎不会记得那个头寸。您的资本比由单个糟糕交易引起的脑雾更重要。

  2. 做出小的损失将确保您活着去做另一次交易。带上尺子(前额叶皮质)和战士心态来执行交易。

当您定期查看交易日志时,特别注意止损。注意自己的感受。这已经不像以前那样情绪化了。你看,这并不那么难。如果你微笑了,太好了。存储那种感觉。您正在建立一个明智交易战士的新神经路径。

盈利退出

下面是盈利退出的逐步方法:

  • 提前决定风险降低的方法:目标价格、跟踪退出、期权。不要偏离。

  • 不要等待熊市反弹。随着人们继续卖出以避免市场冲击,及时*仓。

  • 这是*仓的最小数量,以保持交易盈亏*衡:

  • 顺势而为熊市反弹。让它冲刷过去。如果您提前降低了风险,这不应该影响您的心态。当熊市反弹结束时,重新设置止损。

  • 如果涨势的高点低于上一个高点,则重新进场;否则,不做任何操作。

让我们用一些 Python 代码来结束这一切。首先,我们将使用三个变量来设置目标退出价格:pricestop_lossr_multiplier。我们计算 r 作为从 pricestop_loss 的距离。然后,我们应用一个乘数,恰当地命名为 r_multiplier。这个数字被添加回成本以计算目标价格。然后,我们将使用相同的 r_multiplier 计算要退出的数量。在第七章提高交易优势中,我们看到了目标价格和要退出的数量之间的反向关系。

def target_price(price, stop_loss, r_multiplier):
    r = price - stop_loss
    return price + r * r_multiplier

def partial_exit(qty, r_multiplier):
    if (qty * r_multiplier)!= 0:
        fraction = qty / r_multiplier
    else:
        fraction = 0
    return fraction

price = 100 
stop_loss = 110 
qty = 2000 
r_multiplier = 2 

pt = target_price(price, stop_loss, r_multiplier) 
exit_qty = partial_exit(qty, r_multiplier) 
print('target price', pt,'exit_quantity',exit_qty) 

输出将如下所示:

target price 80 exit_quantity 1000.0 

80%的头寸将会在此时退出。这样可以降低 100%的风险。接下来,让我们考虑如何确定进场时机。

进场

"把市场波动视为朋友而不是敌人;从愚蠢中获利,而不是参与其中。"

– 沃伦·巴菲特

优秀的扑克玩家不是打自己的牌。他们打其他玩家的牌。要成功,您需要系统地将概率倾斜到您的有利。市场碰巧是一个概率游戏。取得伟大成功的方法不仅是打出你的手牌,还要打市场的无形之手。

玩转市场的第一种方法是我们在第五章政权定义中看到的。让市场决定股票应该走哪一边。让我们诚实地说一秒钟。做空泡沫股票的市场参与者是被压抑的复仇交易者。在内心深处,他们对自己的阴影自我没有参与做多感到愤怒。也许他们关闭得太早了。也许他们完全忽视了那艘船。无论哪种方式,他们通过让别人的宝贵资金立即置于危险之中来发泄他们的挫败感。在对“公*”估值的成年人呼吁背后,隐藏着一个 6 岁孩子受伤的自尊心的“必须正确”的阴影需求。

没有比 TSLA 更好地说明这一现象的了。这是一家汽车制造商,处于一个声名狼藉的脆弱行业,被定价为科技股,其债券被定价为垃圾债。必须有所作为。这给了空头卖家充足的理由来猛烈袭击股票。在冠状病毒大流行之后,股价下跌到了$400。这给了空头卖家加倍努力的理由,只是在接下来的六个月里面临着急剧的三倍反弹。

如果做空者将跌幅视为一个机会性的买入机会,他们还会围攻吗?当然不会,他们会笑着跳着去银行。地球上的每个人,从瑙鲁到博博迪乌拉索,都会知道他们选中了那只股票有多聪明。现在,他们被苦苦降低到要求对那个粗鲁价格公正的地步。无论哪种方式,别人的钱不是一个有效的智商测试。再次,他们让自己的自尊心在市场的永恒舞蹈中踩到了自己的脚趾。当心那些玩弄伊卡洛斯股票的卡桑德拉,因为他们可能会将你拖入表现不佳的世界。在听从他们的建议时,为冥界的渡船人留下最后一枚硬币。如果做空游戏是关于玩弄市场的无形之手,那就让市场为你做繁重的工作。做空市场贬低的问题,并在需求旺盛的问题上做多。

第二种玩转市场的方法是掌握时机。多年来,我常常抱怨空头挤压。我进入一个头寸,感觉良好,然后在下一个熊市反弹中被无情地止损出局。财务资本受到损害,情感资本再次遭受侮辱。更重要的是,似乎教训被忽略了。然后有一天,空头挤压的能量突然映照在我的智力密度上。由于价格似乎会在我的“防线”止损线之外反弹,我所要做的就是等待下一个熊市反弹,看看新的海岸线,并获得更好的执行。

我开始将熊市反弹视为礼物。它们将他们的宝藏带到岸边供我们选择。一旦熊市反弹开始消退,价格就会像职业政客一样摇摆不定。做空者被困在岸上。乐观的多头持有者尚未被拖入新的深渊。分界线清晰。在执行交易员英语中,这是一个低风险高回报的入场价格,上方设有明确的止损线,并且可能会有下跌。等待市场开始下跌,然后沿着看跌趋势打印一个新的较低的高点来进入做空。顺便说一句,这是“买入跌势”技术在多头方面的镜像入场。

第三种玩市场的方式是执行。做空者面临着极不利的概率。如果你在股价下跌时做空,只要记住 90%以上的市场参与者只会做多,某个地方某人会将当前的弱势视为折价购买的机会。如果你在熊市股票反弹时做空,你可能会因为被抛售或者牛市的开始而被淘汰。作为一个做空者,只有在概率对你有利的狭窄时间窗口。为此,你需要密切关注价格走势。

一个很好的类比是豹子,是非洲四大动物中最小的。尽管豹子在智商、奔跑速度和武器方面胜过它们的猎物,但它们从不追逐。它们隐藏在树上等待猎物靠*它们。做空者需要以同样的方式行事。这是一个三步过程。

  1. 首先,你的制度分析(来自第五章制度定义)应该已经确定了股票可能处于横向或熊市模式中的一种。与市场一致通常会倾向于增加你的获胜几率。

  2. 第二,宇宙已经被缩小为可投资候选股票的短列表。

  3. 第三,熊市反弹的退潮清晰地表明了牛市并不掌控局面。

市场指导两个步骤:设置和执行。一个步骤来自于分析:可投资候选股票的短列表。我们已经讨论过如何倾斜你的交易优势在第二部分外部游戏:制定强大的交易优势中,但我们将重温一些关键想法:

  • 首先,使用相对系列。

  • 第二,通过制度对表现不佳者和表现优异者进行初步分类。

  • 第三,在高点后进入做空或在低点后进入做多。

  • 第四,将止损设置在一个合理的表达点。

  • 第五,计划部分退出以减少风险。

让我们回到豹子。一旦它扑出去,它就不会在半空中停下来反思生活的意义、动物的残酷性或细胞层面素食饮食的比较优势。反省的时机已经过去。现在,是执行时间。游客会在他们认为是正确的船之后立即跳跃和游泳。专业人士将耐心等待市场上涨并冲洗游客。当反弹进入并翻转时,他们会站在一边,只有在那时他们才会坐在渡轮上。关于卖空的最好消息是熊市反弹的节拍的规律性。

翻转:熊市反弹的合气道

每个长时间练习这门手艺的卖空者在熊市反弹中都受过伤。一个简单的观念转变可以将这种能量从毁灭转变为利用的力量。

目标是尽早以合理的成功概率进入。短线挤压可能会棘手。它们总是超出预期并持续时间更长。

进入大师级别的卖空者的标志是在下一个大幅下跌中做对,但仍然低估了熊市反弹的能量。尊重市场,因为它们肯定不会尊重你。市场不知道你的名字,也不应该在乎。接受你将不得不为确认付出代价。等待局部高峰过去和翻转开始。稍后我们将用几张图来说明这一点,但现在让我们看看这种方法的优点。

这种翻转或潮汐滚动方法有一些优点:

  • 风险管理:当前高点低于峰值。牛市不再掌控局势。如果峰值上升,则是早期迹象表明制度可能已经改变。趋势是你的朋友。

  • 入场接*顶部。熊市处于混乱状态。牛市充满乐观。你是机会主义者。现在概率正倾向于你。

  • 借贷可用性:熊市通常会冲洗掉游客。再次可以借贷。即使最喧哗的卖空者也害怕涉足水中。

  • 更大的头寸大小:接*顶部的*距离需要比崩盘水*更大的头寸。你更接*一个合乎逻辑的止损。如果价格上涨超过当前顶部,则你已经制定好了退出计划

  • 清晰的分界线:顶部是牛市和熊市的定论。有关供给、需求和波动率的信息是可用的。

以下是我们之前讨论过的一些其他经典入场方法。

移动*均线

移动*均线是简单、有效且足够稳健的信号。虽然没有完美的策略,但通常最好使用短期移动*均线,比如收盘价低于 5 天移动*均线。有关移动*均线交叉的更多信息,请参阅第五章制度定义

回撤

回调信号最高点的距离。这可以是从最高高点或最高低点开始的距离,以*均真实范围表示。把它看作是一种形式的移动止损。作为提醒,请看我们在第五章制度定义中概述的回调摆动函数:

def retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct):
    if _sign == 1: # swing high
        retracement = df.loc[hh_ll_dt:, _c].min() - hh_ll

        if (vlty > 0) & (retrace_vol > 0) & ((abs(retracement / vlty) - retrace_vol) > 0):
            df.at[hh_ll_dt, _swg] = hh_ll
        elif (retrace_pct > 0) & ((abs(retracement / hh_ll) - retrace_pct) > 0):
            df.at[hh_ll_dt, _swg] = hh_ll

    elif _sign == -1: # swing low
        retracement = df.loc[hh_ll_dt:, _c].max() - hh_ll
        if (vlty > 0) & (retrace_vol > 0) & ((round(retracement / vlty ,1) - retrace_vol) > 0):
            df.at[hh_ll_dt, _swg] = hh_ll
        elif (retrace_pct > 0) & ((round(retracement / hh_ll , 4) - retrace_pct) > 0):
            df.at[hh_ll_dt, _swg] = hh_ll
    else:
        retracement = 0
    return df 

下面,让我们再次提醒自己关于retest_swing函数。

重新测试

提供在第五章制度定义中的摆动检测代码是基于重新测试的。价格打印出高点,然后是低点。价格试图攀升到新的高点,但失败了,并且低于先前的低点。距离前一次摆动越远,重新测试就越不嘈杂。作为提醒,请参阅源代码:

def retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg):
    rt_sgmt = df.loc[hh_ll_dt:, _rt] 

    if (rt_sgmt.count() > 0) & (_sign != 0): # Retests exist and distance test met    
        if _sign == 1: # swing high
            rt_list = [rt_sgmt.idxmax(), rt_sgmt.max(), df.loc[rt_sgmt.idxmax():, _c].cummin()]

        elif _sign == -1: # swing low
            rt_list = [rt_sgmt.idxmin(), rt_sgmt.min(), df.loc[rt_sgmt.idxmin():, _c].cummax()]
        rt_dt,rt_hurdle, rt_px = [rt_list[h] for h in range(len(rt_list))]

        if str(_c)[0] == 'r':
            df.loc[rt_dt,'rrt'] = rt_hurdle
        elif str(_c)[0] != 'r':
            df.loc[rt_dt,'rt'] = rt_hurdle    

        if (np.sign(rt_px - rt_hurdle) == - np.sign(_sign)).any():
            df.at[hh_ll_dt, _swg] = hh_ll 
    return df 

接下来,我们将考虑一个富国银行的例子,其中重新测试和回调摆动都在起作用。如果一个方法失败,另一个可以补偿。

把所有东西都放在一起

现在是将想法结合起来,并在一个代码块中综合方法的时候了。在第五章制度定义中,我们发布了富国银行与 S&P 500 的绝对和相对系列的图表:

图 12.1:富国银行价格在绝对和相对于 S&P500 的图示从 2015 年 9 月开始

我们已经涵盖了几乎所有内容,所以没有真正需要对代码进行评论,除了两件事:

  1. 我们从初始化基准开始,并下载下面股票的数据。如果您想要为一系列股票重复此过程,请在df下载行之前插入一个循环。

  2. 其次,我们通过列表推导重新初始化了_o_h_l_c属性。这在代码的下一部分将会有意义。

接下来,我们使用摆动检测函数计算了绝对和相对系列的摆动和制度。两次运行相同函数但分配了绝对或相对系列更有效。这就是为什么我们在之前重新初始化了_o_h_l_c以及下面的摆动值。

### STEP 1: ### Graph Regimes Combo ###
def graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,
                       ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi):

#### removed for brevity: check GitHub repo for full code ####
### Graph Regimes Combo ###

### STEP 2: ### RELATIVE
def relative(df,_o,_h,_l,_c, bm_df, bm_col, ccy_df, ccy_col, dgt, start, end,rebase=True):
#### removed for brevity: check GitHub repo for full code ####
### RELATIVE ###

### STEP 3: import library
from scipy.signal import *
### STEP 4: #### hilo_alternation(hilo, dist= None, hurdle= None) ####
def hilo_alternation(hilo, dist= None, hurdle= None):
#### removed for brevity: check GitHub repo for full code ####
#### hilo_alternation(hilo, dist= None, hurdle= None) ####

#### historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None) #### 
def historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None):

#### removed for brevity: check GitHub repo for full code ####
#### historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None) ####
### STEP 5: #### cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo) ####
def cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo): 
#### removed for brevity: check GitHub repo for full code ####
#### cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo) ####
### STEP 6: #### latest_swings(df, shi, slo, rt_hi, rt_lo, _h, _l, _c, _vol) ####
def latest_swing_variables(df, shi, slo, rt_hi, rt_lo, _h, _l, _c):
#### removed for brevity: check GitHub repo for full code ####
#### latest_swings(df, shi, slo, rt_hi, rt_lo, _h, _l, _c, _vol) ####
### STEP 7: #### test_distance(ud, bs, hh_ll, vlty, dist_vol, dist_pct) ####
def test_distance(ud,bs, hh_ll, dist_vol, dist_pct): 
#### removed for brevity: check GitHub repo for full code ####
#### test_distance(ud, bs, hh_ll, vlty, dist_vol, dist_pct) ####

#### ATR ####
def average_true_range(df, _h, _l, _c, n):
#### removed for brevity: check GitHub repo for full code ####
#### ATR ####
### STEP 8: #### retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg) ####
def retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg):
    rt_sgmt = df.loc[hh_ll_dt:, _rt] 
#### removed for brevity: check GitHub repo for full code ####
#### retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg) ####
### STEP 9: #### retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct) ####
def retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct):
#### removed for brevity: check GitHub repo for full code ####
#### retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct) ####
### STEP 10: #### regime_floor_ceiling(df, hi,lo,cl, slo, shi,flr,clg,rg,rg_ch,stdev,threshold) ####
def regime_floor_ceiling(df, _h,_l,_c,slo, shi,flr,clg,rg,rg_ch,stdev,threshold):
#### removed for brevity: check GitHub repo for full code ####
#### regime_floor_ceiling(df, hi,lo,cl, slo, shi,flr,clg,rg,rg_ch,stdev,threshold) #### 

下面是实际重要的代码,将打印出图 12.1所示的图形:

params = ['2014-12-31', None, 63, 0.05, 0.05, 1.5, 2]
start, end, vlty_n,dist_pct,retrace_pct,threshold,dgt= [params[h] for h in range(len(params))]

rel_var = ['^GSPC','SP500', 'USD']
bm_ticker, bm_col, ccy_col = [rel_var[h] for h in range(len(rel_var))]
bm_df = pd.DataFrame()
bm_df[bm_col] = round(yf.download(tickers= bm_ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None)['Close'],dgt)
bm_df[ccy_col] = 1

ticker = 'WFC'
df = round(yf.download(tickers= ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None),2)
#### removed for brevity: check GitHub repo for full code ####

    rohlc = ['rOpen','rHigh','rLow','rClose']
    _o,_h,_l,_c = [rohlc[h] for h in range(len(rohlc)) ]
    rswing_val = ['rrg','rL1','rH1','rL3','rH3','rclg','rflr','rrg_ch']
    rg,rt_lo,rt_hi,slo,shi,clg,flr,rg_ch = [rswing_val[s] for s in range(len(rswing_val))] 

我们首先对绝对系列运行一个循环。我们使用上下限制度方法计算摆动和制度。在第一个循环结束时,我们使用相对系列重新初始化了_o_h_l_c和摆动变量。现在我们已经计算出了富国银行在绝对和相对于 S&P 500 的摆动和制度。让我们可视化结果:

plot_abs_cols = ['Close','Hi3', 'Lo3','clg','flr','rg_ch','rg']
plot_abs_style = ['k', 'ro', 'go', 'kv', 'k^','b:','b--']
y2_abs = ['rg']
plot_rel_cols = ['rClose','rH3', 'rL3','rclg','rflr','rrg_ch','rrg']
plot_rel_style = ['grey', 'ro', 'go', 'yv', 'y^','m:','m--']
y2_rel = ['rrg']
df[plot_abs_cols].plot(secondary_y= y2_abs,figsize=(20,8),
            title = str.upper(ticker)+ ' Absolute',# grid=True,
            style=plot_abs_style)

df[plot_rel_cols].plot(secondary_y=y2_rel,figsize=(20,8),
            title = str.upper(ticker)+ ' Relative',# grid=True,
            style=plot_rel_style)

df[plot_rel_cols + plot_abs_cols].plot(secondary_y=y2_rel + y2_abs,figsize=(20,8),
            title = str.upper(ticker)+ ' Relative & Absolute',# grid=True,
            style=plot_rel_style + plot_abs_style) 

我们将绘制三个独特的图表:绝对、相对和综合。因此,我们将绝对和相对参数存储在列表中。话不多说,这是三个图表:

图 12.2:富国银行的绝对波动和上下限制度

制度一直是行为的一个公*预测因素,特别是在后半段。2020 年的涨势直到 2021 年出现摆动低点才导致制度变化。接下来,我们将绘制相对系列:

图 12.3:富国银行的波动和地板/天花板制度相对于标普 500 指数

正如我们在前面的章节中所看到的,当丑闻爆发时,富国银行受到了重创,直到 2021 年才恢复。制度看起来表面上更加紧张。一路上有相当多的看涨假阳性。它们的范围和持续时间都很短。请注意,价格线上方的红点如何构成良好的入场点和/或移动止损水*。当然,打印波动高点和发现它们之间存在一小段滞后时间。最后,我们将两者合并成一个图表:

图 12.4:富国银行的波动和地板/天花板制度绝对和相对于标普 500 指数

这最后一个图表看起来比前两个更加嘈杂。请注意地板/天花板方法如何准确地命中了 2016 年 9 月的丑闻。相对系列在整个期间始终领先于制度。

让我们再次使用图表制度函数来可视化绝对和相对图表:

ma_st = ma_mt = ma_lt = lt_lo = lt_hi = st_lo = st_hi = 0
rg_combo = ['Close','rg','Lo3','Hi3','Lo3','Hi3','clg','flr','rg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch=[rg_combo[r] for r in range(len(rg_combo))]
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi)

rrg_combo = ['rClose','rrg','rL3','rH3','rL3','rH3','rclg','rflr','rrg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch=[rrg_combo[r] for r in range(len(rrg_combo))]
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

以下是绝对值中绘制的制度:深色表示亏损期:

图 12.5:富国银行在绝对值中着色的地板/天花板制度

接下来,让我们看看相对系列:

图 12.6:富国银行在相对于标普 500 指数的地板/天花板制度着色

这最后一个图表真正展示了过去几年中表现不佳的程度。有许多识别趋势耗尽的方法,例如随机指标、相对强弱指标、移动*均收敛/散开指标、德马克指标以及后者的祖先,斐波那契回调。其中大部分技术归结为将混乱带入秩序。不幸的是,普及并不一定表示统计上的稳健性。如果你仍然相信使用预测性技术分析,你可以将订单分成两部分,第一部分使用预测性分析,第二部分在确认预测准确后添加。当它奏效时,你的*均执行会稍微好一些,并且当它不奏效时,你不会破产。

最重要的是,记住一个人的崩溃对另一个人来说是“低吸买入”。这是空头市场;市场不合作。利用熊市反弹和空头挤压来确定你的入场时机。当每个人都卖光时出局。通过减少仓位和/或重设止损来尽量降低风险。

摘要

整本书都指向了这一章和下一章。总之,为了总结我们在前面章节中所涵盖的所有内容,请切换到相对系列并根据市场制度进行分类。在高点之后进入空头,或者在低点之后进入多头。设定一个在波动之上或之下的止损价格和一个目标价格以降低风险。使用你的成本、止损和风险预算来计算你的头寸规模。

为每个策略的每个多/空侧保留单独的风险预算。尊重你的止损并尊重你的策略。保持一个干净的交易日志。在路上完善你的授权。

在下一章中,我们将研究你工具箱中最被低估的工具之一:你的投资组合管理系统。成为一名选股专家和一名投资组合经理是两种需要不同技能的不同工作。在你选择管理投资组合的那一刻,你不再是一个股票骑手。你已经成为了一个稳定的马主。你的工作不是骑在马背上冲过终点线。你的工作是培育(或淘汰)那些在可预见的未来能(或不能)冲过终点线的马匹。

一个相对的多空投资组合与传统的仅多头投资组合甚至绝对的多空投资组合是完全不同的生物。到目前为止你所使用的任何工具都迫切需要进行根本性的升级。如果你想在市场上有一线生机,你需要一套钢铁侠的装备。

第十三章:投资组合管理系统

"托托,我觉得我们不再是在堪萨斯了。"

– 多萝西,《绿野仙踪》

我在对冲基金世界的第一份工作是为一家管理资金不到 500 万美元的初创对冲基金建立和维护一个名为投资组合管理系统PMS)的系统。创始人认为风险管理不是业务的一种装饰,而是业务本身。快进到现在,他们已经成为日本替代空间的主导者。在本章中,我们将继续上两章的工作,并介绍一个定制的 PMS,它可以显示投资组合的风险可视化。

为了说明健壮的 PMS 的重要性,让我们联系一下我们在本书中探讨过的一些概念。在第一章,《股票市场游戏》中,我们设定了市场是一个无限、复杂的随机游戏的背景。在第六章,《交易优势是一个数字,这就是公式》中,我们揭示了神奇、神秘和神话般的交易优势公式。在第八章,《头寸大小:在资金管理模块中赚钱》中,我们证明了头寸大小决定了绩效。我们在第十一章,《多空工具箱》中学到了我们工具箱中的工具。所以,我们知道头寸大小是关键因素,但我们还不知道哪些头寸会奏效,然而我们必须在管理风险敞口的同时保持正面期望。每天重复这个过程几年,以吸引并保留投资者。

在我的职业生涯中,朋友和同事们慷慨地展示了他们的 PMS。生存直接与他们 PMS 的质量相关。并不是每个拥有正确系统的人都成功了。但每一个没有系统的经理最终都崩溃了。

PMS 就像飞行仪器。任何新手都可以在晴朗的天空中驾驶飞机。仪器的存在是为了防止起飞和在夜间着陆、在雾中和湍流中的坠毁。没有仪器,不是每个人都能回家。市场并非一直是晴朗和顺利的。事情会出乎意料地变得丑陋。情绪确实会使我们偏离轨道。用执行交易员的术语来说,如果你没有一个坚实的 PMS,你怎么能说自己是一个投资组合经理呢?使用 Python 构建定制的 PMS 值得一本书,甚至是自己专门的文学流派,因此超出了本书的范围。然而,在本章中,我们将简要讨论一些基本概念和指导原则,希望能指导你:

  • 糟糕的投资组合管理系统的症状

  • 你的投资组合管理系统就是你的钢铁侠战衣

  • 自动化枯燥的事情

  • 构建一个健壮的投资组合管理系统

您可以通过以下链接访问本章中所有图像的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。您还可以通过该书的 GitHub 存储库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

对于本章和本书的其余部分,我们将使用pandasnumpyyfinancematplotlib库。所以,请记得首先导入它们:

# Import Libraries
import pandas as pd
import numpy as np
import yfinance as yf
%matplotlib inline
import matplotlib.pyplot as plt 

低效的投资组合管理系统的症状

当谈到改善业绩时,一个好的 PMS 是最低的果实。在 2005 年,我加入了一个对 PMS 非常丑陋的对冲基金,看着它可能会导致脑损伤。我立即进行了改进,至少是为了消除健康风险。突然间,问题儿童们就像圣诞树上的花环一样亮了起来。短线股票的波动性减少了,懒惰的狗,和不被赏识的赛犬都被迅速处理了。波动性下降了。表现更加一致了。夏普比率提高了。投资者注意到了。资产管理规模AUM)增长了。就是这么简单。

每个人都想知道赢家的"秘密酱",但这是一个领域,"阿尔法挑战者"的经验可能会帮助我们避免无意中重复同样的错误。这是一个简单的练习,将帮助您判断您的系统是否需要升级。效率低下的 PMS 表现出以下一个或多个症状。

无效的资本配置

尽管投资组合经理们喜欢向公众展示出一个奥林匹克半神的形象,但只需几句话就可以将他们拉回现实:

  • "好人最后完成":一些股票取得了令人印象深刻的回报,但由于头寸较小而未被注意到。这些往往是探索性的小头寸。它们获得高回报,但由于没有足够的规模而贡献不佳。

  • "肥猫不捉老鼠":一些大头寸之所以有所贡献,只是因为它们的重量巨大。这是 PMS 的一个经典问题。它直接与上述问题相关。这些往往是占用了太多空间但回报微薄的高信仰度想法。

  • "曾经我们是勇士":这些是现在免费吃白食的老牌贡献者。这些是一段时间以来变得陈旧的想法。它们有很多嵌入式的历史贡献,但不再产生收益。我们在第七章提升您的交易优势中已经解决了这种情况。

监测不足的风险检测

一个需要密切关注的关键指标是流动性,以避免“加州酒店综合症”。换句话说,你不能清算的东西就不是你拥有的,而是拥有你的。流动性是熊市的货币。是否有头寸不能在不产生严重市场冲击的情况下清算?以下是一个重新计算头寸规模所需天数以便以*均交易量的一部分退出的函数。对于一个空头卖方来说,最可怕的事情就是看到熊市反弹获得动力,并意识到你的头寸过大以至于无法幸免于难。很少有比被迫清仓更糟糕的感觉,只见其在熊市海啸后重新开始向下滑落。

一个简单的风险度量是将头寸规模重新表述为以*均交易量的一部分进行清算所需天数。以下代码简单地计算了*均交易量的一部分。头寸数量除以此分数:

ticker = 'UNG' #ETF natural gas 
volume = yf.download(tickers= ticker,start= '2021-01-01', end = None,                     interval = "1d",group_by = 'column',                     auto_adjust = True, prepost = True,treads = True,                      proxy = None)['Volume']

def days_liquidation(quantity,volume,window,fraction):
    avg_vol_fraction = volume.rolling(window).mean()* fraction
    return round(quantity/avg_vol_fraction,2)
quantity = 100000
window = 63
fraction =0.01
days_liquidation(quantity,volume,window,fraction)[-1] 

这产生了类似以下的输出:

3.52 

我们可以生成图 13.1所示的图表:

plt.plot(days_liquidation(quantity,volume,window,fraction)) 

我们从2021 年初开始下载了交易量数据。该函数将一个固定百分比乘以交易量的移动*均值。这一股数除以交易量的一部分:0.01,或1%。这个值是任意的,且故意设得很低以展示原理。在实践中,5-10%是合理的阈值。截至2021 年 6 月底,如果订单量不超过*均交易量的1%,则大约需要5 天时间来清算整个头寸。我们将系列中的最后一个数字打印出来并绘制了移动*均线:

图 13.1: 以 3 个月*均交易量的 1%进行清算所需天数

上图显示流动性并非静态。最初,对于交易量占*均日交易量1%的头寸,清算大约需要2 天。随着流动性减少,清算所需天数增加到5 天,然后又回落到3.5 天左右。当价格朝着你不利的方向波动时,一周就仿佛是永恒。因此,应该密切监视流动性。

市场冲击是由于大宗交易引起的价格不利变动。当头寸超过日交易量的5%时,市场冲击就会开始。如果头寸量在日交易量的10%下持续时间超过5 天,那么就预期会产生一些严重的市场冲击。此外,熊市反弹的激烈程度不容小觑。在尝试从困境中解脱时,你将心理上处于被动状态。因此,始终要密切监视流动性,并在交易量减少时减少头寸。

高波动性

拥挤的空头有较高的*均借贷利用率。流动性将变薄,波动性将增加,回报将恶化。利用率或借贷费用的热度图是非常有价值的工具。在发布日期,遗憾的是没有免费的资源可以提供借贷利用率。作为一个捷径,当借贷费用大大高于*均水*时,可以假设受欢迎。处理拥挤的空头的最简单方法是随着受欢迎程度的提高减少头寸规模。再次强调,制定简单的规则,例如,如果利用率上升到 40%以上,则将头寸减半,每增加 10%再减半。到达 60%的利用率时,曝光将是原始规模的 25%。这只是一些思考。

爆炸并不显眼:人们希望感觉良好。在市场上,做自己感觉良好的事情很少是最赚钱的行动。处于风险中的股票必须在视觉上促使管理者采取行动。股票很少出现意外爆炸。它们通常会发出微妙的信号表明事情不如预期发展。

高相关性

多元化的目标是降低相关性。相关性很难避免。在第四章多空方法:绝对和相对中,我们介绍了相对系列以减少与基准的相关性。然而,焦点从确定绝对顶部或底部转移到捕捉行业轮换,并相应地分配资产。投资组合内的相关性很难消除。坦率地说,我不知道如何在实践中做到这一点。迄今为止,我也没有遇到成功的方法。

曝光管理不善

有几种不同类型的曝光,可以通过以下方式表明投资组合管理不善:

  • 净曝光:当投资组合的净曝光与当前的看涨/看跌观点不匹配时。这在熊市阶段尤其明显,当环境愁云密布时,净曝光仍然指向残存的乐观情绪。投资组合认知失调是指曝光不反映管理者的说法。

  • 净贝塔暴露:大多数不足系统中缺乏真正的市场敏感性。当管理者只关注净曝光时,他们将低方向性与净市场敏感性混为一谈。净贝塔进一步超越净曝光,以反映对市场的敏感性。

  • 市值暴露:做空期货是对冲的垃圾食品。正如我们在第十一章多空对冲工具箱中看到的那样,小盘股和大盘股具有不同的风险特征。当市场整体情绪乐观时,小盘股表现良好,而大盘股是更安全的选择。净市值暴露反映了投资组合的整体乐观情绪。

  • 总曝光:在好时机杠杆过多,在坏时机现金过多。总曝光是最容易减少或增加风险的杠杆。犹豫不决时,崩溃杠杆是最简单的风险政策。

  • 交易所暴露:按市值和交易所暴露的暴露解释了很多好/坏的表现。正如我们在 第四章长/短期方法论:绝对和相对 中所看到的,纳斯达克多年来一直优于标普 500。多年的轻松赚钱奖励了投机问题和那些押注于它们的人。当钱容易赚时,就容易赚钱。没有牛市曾经提高过任何人的智商。

总的来说,在资产管理行业,投资回报率最高的是定制的 PMS。随着信息差的缩小,市场参与者争先恐后地寻找优势。如果你能比你的同行更早地发现和解决问题,你就能获得可持续的竞争优势。

你的投资组合管理系统就是你的钢铁侠服

"你知道,我经常被问到的问题是,“托尼,你怎么在你的衣服里上厕所?” [长时间的停顿] 就是这样。"

– 托尼·斯塔克,《钢铁侠》

托尼·斯塔克可能是个天才、亿万富翁、花花公子和慈善家。真正赋予他超能力的是他定制的钢铁侠服。他没有在 Macy's 的货架上买他的衣服。他在车库里摧毁了几辆兰博基尼,打造了一些独特增强他战斗风格的东西。同样,你的 PMS 就是你的钢铁侠服。它是你交易策略的延伸。它的唯一目的是帮助你在不确定性下做出交易决策。因为没有人像你一样交易,所以它需要高度定制化。

经典错误是购买昂贵的现成软件包,认为更多的信息会导致更好的交易决策。软件解决方案主要是由中后台人员为前台专业人员设计的报告工具。你的 PMS 是一个交易工具,而不是报告工具。Barra 因子分解或街头共识每股收益不会告诉你今天应该买入或卖空哪家公司的多少股票。信息转化为知识,而知识并不直接转化为技能。建立技能的关键是专注于直接导致行动的信息。

在实践中,系统整合几个月后,投资组合经理经常以低技术的 Excel 电子表格来管理他们的投资组合,这些电子表格从那些闪闪发光的玩具中获取数据。他们买了一辆兰博基尼去挑牛奶。因此,在你急于购买市场上最昂贵的玩具之前,这里有几个原则可以帮助你澄清自己的需求。信息必须根据四个原则组织:清晰、相关、简单和灵活。

清晰:绕过左脑

在压力下,你的杏仁核会释放化学物质,降低前额叶皮层或“思考大脑”的活动。你的思维能力会受到影响。你的 PMS 需要清晰度:信息必须组织得让问题迅速显现出来。其次,左脑无法处理数字的行和列。它慢慢的,每秒 5 到 7 位。它不会做关联。一切都变得模糊成无生机的数字汤。与此同时,右脑处理信息的速度快一百倍,寻找模式,并做关联。幸运的是,数据可视化是数据科学的新趋势。视觉线索能够绕过思考较慢的大脑。当决策涉及多个因素时,按照数字进行绘画有助于建立关联。例如,将你在投资领域内的位置可视化为热图会立即告诉你是否在正确的轨道上,并在每个行业内选择最佳策略。我们将在本章结束时查看投资组合热图。

另一个话题是警报。你是否曾想过为什么灾难警报是如此讨厌?如果《欢乐颂》宣布即将发生地震、海啸或火山喷发,人们可能不会感到同样的紧迫感。我们天生倾向于远离痛苦,向着愉悦之处前进。警报的存在是为了迫使最不情愿行动的人采取行动。当一个位置需要处理时,尽可能地让警报烦人。警报越烦人,解决问题的可能性就越大。最好的警报是你必须在执行日常任务之前手动确认的那些。例如:假设某只股票已达到止损位。如果设置了警报,你必须点击它才能继续查看你的投资组合,那么可能会发生两种情况。要么你会迅速解决问题,要么你会彻底避免使用这个工具。当正确的需求超过了赚钱的必要性时,我们内心的白痴就会更加努力地自我破坏。

经典错误之一是为每个风险因素都设立多个页面。这意味着用户必须在页面之间来回切换并做笔记。每增加一点摩擦力都会增加信息泄漏的可能性。飞行员不应该在飞机上上上下下地查看液压和燃油表是否一切正常。如果你想要将不同的风险联系起来,你需要将所有相关信息汇总到一页摘要中,以便在后续页面进行深入了解。可以把它想象成汽车或飞机的仪表板。你需要的所有信息都在你面前展示着。

将事物放在上下文中。左脑不能有效处理数字。295%的总暴露只是一个数字。当它在显示基准、总和净暴露以及表现的图表上绘制时,这个数字就在上下文中了。它是市场表现、你的位置以及随时间的结果表现的视觉呈现。一张图胜过千言万语。让我们回顾一下在第十一章多空工具箱中看到的例子。我们从以下股票代码模拟了一个投资组合。我们假设从 2020 年 12 月 31 日到 2021 年 6 月期间没有交易:

# Chapter 13: Portfolio Management System
K = 1000000
lot = 100
port_tickers = ['QCOM','TSLA','NFLX','DIS','PG', 'MMM','IBM','BRK-B','UPS','F']
bm_ticker= '^GSPC'
tickers_list = [bm_ticker] + port_tickers
df_data= { 
'Beta':[1.34,2,0.75,1.2,0.41,0.95,1.23,0.9,1.05,1.15],
'Shares':[-1900,-100,-400,-800,-5500,1600,1800,2800,1100,20800],
'rSL':[42.75,231,156,54.2,37.5,42.75,29.97,59.97,39.97,2.10]
}
port = pd.DataFrame(df_data,index=port_tickers)
port['Side'] = np.sign(port['Shares'])

start_dt = '2021-01-01'
end_dt = '2021-07-01'
price_df = round( yf.download(tickers= tickers_list,start= '2021-01-01', 
                              end = '2021-07-01', interval = "1d",                               group_by = 'column',auto_adjust = True,                               prepost = True, treads = True,                               proxy = None)['Close'],2)

bm_cost = price_df[bm_ticker][0]
bm_price = price_df[bm_ticker][-1]

port['rCost'] = round(price_df.iloc[0,:].div(bm_cost) *1000,2)
port['rPrice'] = round(price_df.iloc[-1,:].div(bm_price) *1000,2)
port['Cost'] = price_df.iloc[0,:]
port['Price'] = price_df.iloc[-1,:] 

第十一章多空工具箱中,我们处理了port数据框。这次,我们将使用price_df可视化曝光。我们首先计算基准收益。然后,我们将计算相对和绝对的长期和短期市值。

我们将计算绝对和相对的曝光和收益。

price_df['bm returns'] = round(np.exp(np.log(price_df[bm_ticker]/price_df[bm_ticker].shift()).cumsum()) - 1, 3)
rel_price = round(price_df.div(price_df['^GSPC'],axis=0 )*1000,2)

rMV = rel_price.mul(port['Shares'])
rLong_MV = rMV[rMV >0].sum(axis=1)
rShort_MV = rMV[rMV <0].sum(axis=1)
rMV_Beta = rMV.mul(port['Beta'])
rLong_MV_Beta = rMV_Beta[rMV_Beta >0].sum(axis=1) / rLong_MV
rShort_MV_Beta = rMV_Beta[rMV_Beta <0].sum(axis=1)/ rShort_MV

price_df['rNet_Beta'] = rLong_MV_Beta - rShort_MV_Beta
price_df['rNet'] = round((rLong_MV + rShort_MV).div(abs(rMV).sum(axis=1)),3)

price_df['rReturns_Long'] = round(np.exp(np.log(rLong_MV/rLong_MV.shift()).cumsum())-1,3)
price_df['rReturns_Short'] = - round(np.exp(np.log(rShort_MV/rShort_MV.shift()).cumsum())-1,3)
price_df['rReturns'] = price_df['rReturns_Long'] + price_df['rReturns_Short']

MV = price_df.mul(port['Shares'])
Long_MV = MV[MV >0].sum(axis=1)
Short_MV = MV[MV <0].sum(axis=1)
price_df['Gross'] = round((Long_MV - Short_MV).div(K),3)
price_df['Net'] = round((Long_MV + Short_MV).div(abs(MV).sum(axis=1)),3)

price_df['Returns_Long'] = round(np.exp(np.log(Long_MV/Long_MV.shift()).cumsum())-1,3)
price_df['Returns_Short'] = - round(np.exp(np.log(Short_MV/Short_MV.shift()).cumsum())-1,3)
price_df['Returns'] = price_df['Returns_Long'] + price_df['Returns_Short']

MV_Beta = MV.mul(port['Beta'])
Long_MV_Beta = MV_Beta[MV_Beta >0].sum(axis=1) / Long_MV
Short_MV_Beta = MV_Beta[MV_Beta <0].sum(axis=1)/ Short_MV
price_df['Net_Beta'] = Long_MV_Beta - Short_MV_Beta 

rel_price框架是price_df数据框除以基准收盘价乘以 1,000 的结果。我们使用连续系列,不重新调整到系列的开始。索引在开始时的值有 4 位小数。因此,我们将相对价格乘以 1,000 以获得更容易处理的数字。我们将价格乘以股份数,按持仓的符号汇总,然后求和以获得相对的长期和短期市值。由于没有交易,除了收益外,市值没有变化。因此,我们使用市值的日变化来计算累积收益。正如我们在第十一章多空工具箱中看到的,总暴露使用绝对系列。这是实际的资产负债表使用情况。

我们将主要的曝光和收益绘制在一张图上。然后我们绘制相对系列:

price_df[['bm returns','Returns','Gross','rNet_Beta','rNet' ]].plot(
    figsize=(20,8),grid=True, secondary_y=['Gross'],
    style= ['r.-','k','g--','g-.','g:','b:','c','c:'],
    title = 'bm returns, Returns, Gross, rNet_Beta, rNet')

price_df[['bm returns', 'Returns', 'rReturns', 'rReturns_Long',
          'rReturns_Short']].plot(figsize=(20,8),grid=True,
             style= ['r.-','k','b--o','b--^','b--v','g-.','g:','b:'],
             title= 'bm returns, Returns, rReturns, rReturns_Long, rReturns_Short')
price_df[['bm returns','Returns','rReturns',
          'rReturns_Long','rReturns_Short','Returns_Long',          'Returns_Short']].plot(
            figsize=(20,8),grid=True,secondary_y=['Gross'], 
            style= ['r.-','k','b--o','b--^','b--v','k:^','k:v',],
title= 'Returns: benchmark, Long / Short absolute & relative')
price_df[['bm returns',
          'rReturns_Long','rReturns_Short','Returns_Long',          'Returns_Short']].plot(
            figsize=(20,8),grid=True,secondary_y=['Gross'], 
            style= ['r.-','b--^','b--v','k:^','k:v',],
title= 'Returns: benchmark, Long / Short absolute & relative') 

我们将有四张图。第一张是"你是谁?"图表:

图 13.2:"你是谁"图表:市场回报和曝光

上面的图表是我个人最喜欢的。如果有一张图能总结一个经理的投资组合管理技能,那就是这张图。它展示了经理如何应对市场的挑战。基准市场回报是实线红色线,所有其他线都是经理的反应:

  • 总暴露是虚线。杠杆是自信的直接体现。上升的总暴露显示了信心。

  • 净暴露是虚线。净暴露象征着乐观情绪。上升的净暴露表明看涨情绪增长。由于投资组合的两边都表现不错,空头减少,而多头增值。这导致了净多头漂移。

  • 净β是虚线。净β象征着风险偏好。当风险增加时,更多的投机性问题将出现在多头股票中,而防御性行业和股票将出现在空头。没有交易,所以净β只是市值演变的反映。

  • 最后,实线黑线是回报。以这种方式管理曝光带来了这样的表现。

  • 这张图表中唯一缺失的组件是净交易。将净多头/空头交易绘制成条形图,这将显示出响应。由于这个例子中没有交易,所以没有条形图。

接下来,让我们看看长头寸和空头寸如何影响绩效。我们最初的前提是,多空投资组合是两个相对头寸的总和。多头头寸必须胜过指数,而空头头寸必须落后于基准。这是它是如何实现的:

图 13.3:回报:基准、绝对、相对、多头和空头

在实践中,短时间内持续跑赢指数是极为罕见的。红色实线是基准。虚线蓝线是相对绩效,实线黑线是绝对绩效。

首先,多空绩效超过了指数。这是这本书将会得到的最接*虚构的部分。相对多头回报是向上的三角形。空头相对回报是向下的三角形。其次,请注意多头和空头相对回报与指数的接*程度。它们是超过指数的多余回报。将这与我们在《第四章》多空方法论:绝对和相对中看到的相对牛市或熊市中的股票数量相比较。它们在基准周围振荡。

要充分理解超额回报的含义,让我们将相对多头/空头回报与绝对回报进行比较:

图 13.4:回报:基准、绝对、相对、多头和空头

这张嘈杂的图表显示了绝对多头和空头回报。这展示了一个原则,对许多绝对交易者来说仍然陌生。在牛市中从空头赚钱意味着尽可能少地亏损。保持*衡是一件好事。从你在熊市中的多头头寸来考虑一下。你不指望赚到任何钱,而且坦率地说,如果你的多头头寸不被清仓,你会感到高兴。

让我们删除绝对和相对净回报,集中关注多头和空头的绝对和相对回报,以强调这一点:

图 13.5:回报:基准、绝对、相对、多头和空头

用执行交易员的英语来说,在牛市中期望你的空头亏损。只需确保不让小伤口变成感染并使整个投资组合坏死。这是许多新手空头卖方犯的经典错误,他们经常缩小空头头寸。以下是这种三段论通常的推理方式:

  1. 多空领域是一项竞争激烈的运动。每一个基点的绩效都很重要。

  2. 这本短小的书正在泄漏阿尔法,金融黑话中意味着亏钱。

  3. 所以,让我们缩小空头头寸来止血阿尔法出血,并专注于多头。

这种思维方式通常会导致空头市场萎缩。这扩大了净暴露度,并增加了净贝塔。这直接增加了与市场的相关性和收益的波动性。这两个正是投资者愿意支付溢价以避免的。卖空是一种在不使用时会萎缩的肌肉。总之,专注于你的授权、你的暴露度以及相对于指数的超额收益。

关联性:钢铁侠自动收音机效应

尽管他的服装里有很多小工具,但你是否曾想过为什么托尼·斯塔克的钢铁侠装备中没有低科技的自动收音机?他还是 Stark Industries 的 CEO,也许他想知道市场专家对他的股价有什么看法。然而,在与坏人战斗时,倾听 CNBC 上的金融噪音显然是托尼·斯塔克无法承受的干扰。

钢铁侠自动收音机效应是市场参与者有时会引用人类对他们可以管理的股票数量的限制的原因。你的 PMS 并不在这里提供信息。它是你交易策略的延伸,这里是告诉你该做什么的地方。它将输出订单,这些订单要么来自你的策略信号,要么来自你的风险管理。你不需要知道你的夏普比率或共识 EPS 2 年后才能执行止损。你需要知道你的主要暴露度,以及根据你在第十一章长/短工具箱中设计的授权来对冲你的投资组合需要交易多少股票。

每个人都有一个监视屏幕,显示他们的投资组合的情况。很少有市场参与者采取额外步骤构建一个交易屏幕,将他们的交易规则嵌入其中,并将信息处理成交易决策。

构建一个单独的交易表,每个交易决策都有一个列:止损,获利,时间退出,重新进入等等。让你的交易规则或投资流程在后台运行。当需要做出决策时,在相应的单元格中显示股票数量,否则留空。

例如,当一支股票达到了盈利目标时,只需打印出需要关闭的股票数量。

第十一章长/短工具箱中,我们进行了比例风险调整。首先,我们将重新发布代码。我们将展示调整前后的聚合数据。然后我们将打印出订单:

# Chapter 13: Portfolio Management System
adjust_long = adjust_short  =  -0.01 

MV = port['Shares'] * port['Price']
port['Weight'] = round(MV.div(abs(MV).sum()), 3)
port['rR'] = (port['rCost'] - port['rSL'])
port['rRisk'] = -round(np.maximum(0,(port['rR'] * port['Shares'])/K), 4)
port['rRAR'] = round( (port['rPrice'] - port['rCost'])/port['rR'], 1)
port['rCTR'] = round(port['Shares'] * (port['rPrice']-port['rCost'])/ K,4)
port['CTR'] = round(port['Shares'] * (port['Price']-port['Cost'])/ K,4)
port_long = port[port['Side'] > 0]
port_short = port[port['Side'] < 0]
pro_rata_long = port_long['rRisk'] / (port_long['rRisk'].sum() * port_long['rRAR'])
risk_adj_long = (abs(adjust_long) * pro_rata_long * K / port_long['rR'] // lot) * lot
shares_adj_long =  np.minimum(risk_adj_long, port_long['Shares'])*np.sign(adjust_long)

pro_rata_short = port_short['rRisk'] / (port_short['rRisk'].sum() * port_short['rRAR'])
risk_adj_short = (abs(adjust_short) * pro_rata_short * K / port_short['rR'] // lot)*lot
shares_adj_short = np.maximum(risk_adj_short,port_short['Shares'])*np.sign(adjust_short)

port['Qty_adj'] = shares_adj_short.append(shares_adj_long)
port['Shares_adj'] = port['Shares'] + port['Qty_adj']
port['rRisk_adj'] = -round(np.maximum(0,(port['rR'] * port['Shares_adj'])/K),4)
MV_adj= port['Shares_adj'] * port['Price']
rMV_adj = port['Shares_adj'] * port['rPrice']
port['Weight_adj'] = round(MV_adj.div(abs(MV_adj).sum()),3)
port.loc[port['Shares_adj'] != 0,'Shares_adj'] 

我们决定在长空两侧风险上等比例更新,减少-0.01,这相当于将风险降低了 1%。比例调整的排序关键是相对风险调整收益。相对风险单位的相对表现越低,调整就越大。调整后的股票和需要交易的数量是:

QCOM     -1500 
NFLX      -200 
DIS       -500 
PG       -5100 
IBM        500 
BRK-B     2100 
UPS        800
F        19200 

你可以调整 adjust_longadjust_short 变量的值,以适应你想要进行的风险调整(正或负)。添加一个价格列,另一个订单类型列,这就是系统必须输出的全部内容。每次喝一杯葡萄酒时,你不需要了解关于苹果酸乳酸发酵和桶中陈年的任何知识。

简单:复杂性是一种懒惰的表现

当你为生命而战时,你不需要一身沉重、闪闪发光的阅兵服。你需要斯巴达装甲——轻便、有效、经过战斗考验。

当你开始构建你的 PMS 时,你会忍不住想要添加更多的花哨功能。复杂性是一种懒惰的表现。只构建必要的东西,而不是好看的东西。例如,如果你交易移动*均线,你不需要四列价格、第一和第二个移动*均线以及股票。这是信息过载。你只需要一列股数或交易的权重,只有当条件满足时才显示。

你的 PMS 不需要重复发明轮子。Prime 经纪人通过他们的 API 提供了许多你所需要的信息。例如,性能计算是一种资源浪费。它涉及公司行为,如股票拆分、股利和认购/赎回。这些都纳入修改后的 Dietz 时间序列性能计算,按股份类别分开。与此同时,你的 prime 经纪人将在每天早餐前通过他们的 API 提供净资产值NAV)和性能计算。

经验法则是只显示会导致决策的信息,直接的,比如要进行的交易,或者间接的,比如开放风险水*。另一个例子是借用利用率。你的系统为 x 千股的做空交易。你开始流口水,但是系统也显示借用利用率大约是 40%。交易较小的规模可能更明智。

灵活性:信息不能转化为决策

使用 PMS 配备经理就像给*视眼人士配眼镜。起初,他们很高兴能看到任何东西。然后,他们开始要求更多。视力带来视野。一个经典错误是在弄清楚你需要什么之前购买昂贵的软件。软件解决方案是由中后台人员为前台战士构思的。这往往导致前台人员只使用软件功能的一小部分,并在 Excel 上构建一个独立的工具。

另一个错误是从一开始就将所有内容硬编码。您的 PMS 将随着您的发展而发展。每一个小的改进都会产生连锁反应。当人们开始锻炼时,晚上出去喝酒的前景就不那么吸引人了。没有人像你一样交易,所以没有人能够替代你。它不必完美,但必须首先工作。开始时,使其廉价和灵活。Excel、Google 表格、R、Python 和 Jupyter 笔记本足以开始实验。理论上,C++比 Python 更快。在实践中,C++比 Python 慢几个月,甚至几年。Python 是新的 Excel!

自动化枯燥的事情

所有市场参与者都想成为下一个吉姆·西蒙斯。没有人想要照顾管道。人们想做激动人心的事情。他们想要拿出十亿美元的创意来交易。他们不想照顾风险管理。本节介绍了一些耗时且最终令人厌烦的流程的示例,应该进行自动化以及原因。

交易对账是将下单与执行交易进行对账的过程。它显示了哪些交易以什么价格进行了。这是少数几个会让人觉得阅读税法是一项激动人心事业的任务之一。然而,这是一项重要的任务,因为这些数据被用于执行交易分析。价格是否击败了成交量加权*均价格VWAP)?

更新 PMS 很无聊,但并不像看起来那么容易。公司会经历各种各样的公司行动,比如股息和股票拆分。这些公司行动会影响数据的一致性。这需要注意细节。

自动化交易订单路由。绝大多数算法交易员都已经自动化执行。毕竟,如果系统说“买这么多”或“卖那么多”,那就这么做。执行是自动的。自主交易员仍然在全面信任他们的系统方面有困难。如果系统输出一个荒谬的数字怎么办?或者,市场做了这个或那个?好吧,信任是建立的。一个简单的解决方案是默认进行自动执行,除非有手动覆盖。

构建健壮的投资组合管理系统

以下是构建健壮的 PMS 的快速逐步指南。请记住,每个 PMS 都需要高度定制。你正在构建自己的钢铁侠战衣。因此,本指南将保持相当模糊。

  • 将您的策略形式化为简单的交易决策:买入/卖出、数量、价格。交易序列相当简单。绘制一个流程图并填充序列。

  • 添加源自风险管理的决策:流动性、权重、借用利用率、净β值和总体和净敞口。我们之前看到整个投资组合的风险降低。

  • 从您的监控工具中,为每个交易决策创建一个单独的交易表格,每个交易决策在单独的列中。这种极简监控工具对于大型投资组合尤其有效。

  • 在你的视野之外,嵌入你的交易规则。这可以是表格最右侧的列,Excel 中的宏,以及 Python 中的脚本。你只需要你盘子上的香肠,而不是整个烹饪过程的视觉。

  • 在你的视野中,使用股票代码作为行索引,使用交易决策作为列索引来索引你的投资组合。

  • 决策可视化:如果触发了交易决策,请在相应的单元格中打印股票数量或权重,并将其他所有内容留空。这会增加视觉冲击力。

  • 从基于规则的操作开始小规模尝试:止损或获利都是低成本高影响的决策。

  • 随着时间的推移,建立一个综合工具。将你的交易历史添加到直接计算头寸大小。一个强大的工具是将你的投资组合监控工具和观察清单整合到市场热图中。

  • 丢掉汽车收音机。随着你完善流程,你会有添加单元格和列的冲动。再努力一点,尽量保持尽可能多的内容在后台运行。

第十一章多空工具箱 中,有一张扩展表格,其中列出了要交易的股票。我们按方向(多头或空头)和相对风险调整收益 (rRAR) 重新排序数据框。我们切片数据框以仅显示相关列:

port = port.sort_values(by=['Side','rRAR'])
port_cols = ['Side','Beta','Shares_adj','Weight',             'Weight_adj','CTR','rCTR',
             'rRAR','rRisk','rRisk_adj']
port[port_cols] 

一切看起来都像这样:

让我们将上述表格放在投资组合管理框架中加以解释。

  • 让我们首先将投资组合的一侧和对市场的敏感性可视化。我们想知道高/低 beta 位于哪一侧。我们是看涨还是看跌?

  • 接下来,我们想要做出我们的交易决策。我们不需要最终在最后一列得出结论。我们想要知道首先要做什么。然后,我们可以检查系统是否按预期工作。

  • 我们已经知道调整会减少我们的总敞口。现在,我们想知道每个头寸的调整前后影响。这些是“权重”和“权重调整”列。

  • 风险纯粹主义者会在权重旁边显示风险的影响。我们的资产配置重点是按绩效比例减少风险而不是按权重。我们首先想要修剪表现不佳的头寸。因此,我们显示贡献,“CTR”,“rCTR”以及相对风险调整收益,“rRAR”。

  • 最后,我们显示“rRISK”和“rRisk_adj”之前和之后的相对风险。最后一列显示了股票级别的投资组合剩余风险。

这个概念框架已经被简化到其最基本的组成部分。每一列中的每个数字都有其存在的理由。即使是办公室纸牌和俄罗斯方块大师的顶尖人物,也就是合规和风险官员,也会同意这是根据行业中最严格的风险管理指南编制的,用俚语说就是“我不知道,看起来似乎不会炸掉农场”。

唯一的问题是,我们的左脑半球不具备处理这些信息的能力。这是一个大脑无法处理的单调数字汤,更不用说与之相关了。有意识的大脑每秒只能处理 5 +/-2 位信息。用执行交易员的术语来说,当你的眼睛从表格的一端移到另一端时,你的大脑已经忘记了它一开始需要寻找的东西。另一个不好的消息:你并不特殊。这种情况发生在每个人身上。此外,雷曼,如果你能记住这个表格,你会在二十一点桌上数牌时过得更好。

真正的问题是,我们如何将这种单调的数字汤转化为我们一瞥就能准确处理的东西?原来我们的大脑配备了右脑半球。它以闪电般的速度处理信息,将看似随机的数据片段进行关联。唯一的缺点是,数据需要重新打包成这种大脑能够处理的格式。用执行交易员的术语来说,让我们按照数字来绘制。我们将使用一个名为 Styler 的内置构造器。只需几行代码就能返回一个多功能的热图。这几行代码可以循环利用,以绘制市场回报的快速有效的热图。

perf_cols= ['rCTR', 'CTR','rRisk', 'rRisk_adj','rRAR']
desc_cols= ['Side','Beta','Weight','Weight_adj',]
sort_cols = ['Side','rRAR']
asc = [True,True]
port[port_cols].sort_values(by = sort_cols,ascending= asc).style.background_gradient(
    subset = desc_cols, cmap = 'viridis_r').background_gradient(
    subset = perf_cols, cmap = 'RdYlGn').format('{:.5g}') 

我们运行一个多空头投资组合。出现在空头的数字通常带有负号。我们不希望我们的潜意识将空头仓位与负收益联系起来。因此,我们将描述性字段(desc_cols)与与绩效相关的字段(perf_cols)分离开来。您想要在单个数据框上显示的颜色图数量越多,就越简单地将它们堆叠在一起。

sort_values 方法被添加以进一步增强热图的多功能性。这个单调的数字汤只有在正确绘制时才会变得生动起来。西斯廷教堂的壁画可能看起来神圣,但它们背后只是一堵墙。

一张计算机截图  描述以低置信度自动生成

图 13.6:投资组合热图

这个热图按照多空头(long/short)和相对风险调整回报(rRAR)排序。数字被绘制后变得生动起来。这张表格可以进一步简化。再次指导原则是尽可能少地显示干扰。让我们注意到这个显示的改进:

  • 首先,数量、成本、价格和止损列被隐藏起来。它们是重要信息,但不是关键信息。不关键的信息可能会分散注意力。如果触发了止损,您需要知道需要交易多少股票。在那之前,它们只是干扰。

  • 在这个例子中,前五列严格是描述性的。要交易的股票数量没有额外的含义。因此,它不需要上色。

  • 其他描述性列采用黄色到绿松石到紫色的颜色代码。侧面立即显示我们正在处理书的哪一面。贝塔显示我们是如何被斧头砍的。看起来大部分低贝塔的东西都在空头方向上。调整后的风险仍然很高的股票仍然是调整前/调整后最大的权重。

  • 其他所有内容都采用了三色图案的颜色编码,从红色到橙色到绿色,表示每个单元格的健康状态或权重。这个系统有效。

这里有其他可视化想法。构建 PMS 时,专注于对你有共鸣的内容。这是你的钢铁侠装甲。有些人喜欢表格,并使用热图。有些人对图表有反应。在下一个代码块中,我们将以条形图的形式可视化信息。我们将使用不同的键对数据进行排序,以展示不同的视角。

bar_cols= ['Weight', 'Weight_adj','rRisk','rRisk_adj','rCTR',            'CTR','rRAR','Side']
col_style= ['lightgrey','dimgrey','lightcoral','red',
            'forestgreen','lightseagreen','yellowgreen','whitesmoke']
sort_keys= ['Weight_adj','rCTR']
sec_y=['rRAR','Side']
sort= ['rRAR']
port[bar_cols].sort_values(by=sort).plot(kind='bar',
            grid=True,figsize=(20,5),
            secondary_y=sec_y,color=col_style, title= 'PORT, by '+str(sort))

sort= ['Weight_adj','rRAR']
port[bar_cols].sort_values(by=sort).plot(kind='bar',
            grid=True,figsize=(20,5),
            secondary_y=sec_y,color=col_style, title= 'PORT, by '+str(sort))

sort= ['Side','rRisk_adj']
port[bar_cols].sort_values(by=sort).plot(kind='bar',
            grid=True,figsize=(20,5),
            secondary_y=sec_y,color=col_style, title= 'PORT, by '+str(sort)) 

代码中没有什么特别的,除了颜色代码。把颜色编码交给一个法国人,那个传说中的猪会有浅粉色和薰衣草色的口红,让人联想到夏季的莫奈花园。

我们使用了三个不同的排序键来展示三个不同的视角下的数据:

图 13.7:按“rRAR”排序的投资组合

排序键是 rRAR,无论侧面如何都按升序排序。总体而言,图表的前半部分被多头占据。牛市的潮水会推高所有股票。尽管空头书籍尚未产生大量绝对资金,但已经实现了巨额回报。

其次,我们按“权重”和“rRAR”排序:

图 13.8:按“权重”和“rRAR”排序的投资组合

这将所有东西重新分类为长/短期书籍,并为投资组合提供“rRAR”视角。最重要的职位是最好的风险调整贡献者,这与该投资组合管理策略一致。

图 13.9:按“侧面”和“rRisk_adj”排序的投资组合

这按“侧面”和相对风险后调整的“rRisk_adj”排序。这将产生一个两面的图表,左边是空头,右边是多头。结果与该策略一致。表现最佳者拥有更大的权重和更高的风险。接下来,让我们看一下市场参与者最喜欢的跟踪工具:观察名单。

除非嵌入了一些交易决策,否则观察名单是惰性的。我们都错过了一些交易,只是因为我们没有关注。以下是一种逐步方法,可以确保您保持健康的可操作观察名单:

  • 输入股票代码、目标水*、入场日期

  • 自动化触发器:当价格达到目标水*时,打印要交易的股票数量,否则留空

  • 淘汰陈旧的想法:定期按日期排序。每次审查后删除陈旧的想法

  • 每天对列表进行一次排序

这个半自动化的观察清单将使您与竞争对手区分开来。市场参与者很少花时间正式化他们的计划。当其他人试图在恐惧中即兴发挥时,您将以合理的计划出现。

这个过程可能需要几周,甚至几个月,具体取决于您的正式化水*。定制的 PMS 将带来以下积极效果:

  • 它将迫使您正式化您的过程。如果投资是一个过程,那么自动化就是合乎逻辑的结论。这个原则自工业革命开始就经受了时间的考验。计算机处理的发展已经加强了它。

  • 它将揭示您的过程中的缺陷。自由裁量和半自动化的市场参与者有盲点。

  • 它将减少情绪干扰:在监视屏幕上做出决策是 100%自由裁量的。运行算法是 100%系统化的。您将处于这个谱系的某个位置。

  • 它减轻了压力:当所有决策在后台运行并且只在需要时显示时,您不需要担心并且采取预防性措施。

  • 它释放了精神带宽,可以管理更多的名称或花更多时间思考。当您的系统与您的过程保持一致时,您将花费更少的时间担心,换句话说,消耗精神带宽,更多时间规划。

当您是一名分析师或业余零售交易者时,您是一名股票骑师。您支持一些股票。您参与其中,但您不会因为挂着百万美元的股票而难以入眠。当您选择成为投资组合经理时,您不再是一名骑师。您承担了稳定大师的责任。您的工作是在您的马厩中优化有限的资源。这就是为什么您需要一个 PMS。

概要

投资于 PMS 是您将会做出的最高回报投资决策。没有 PMS,您可能会偶尔运气好地挑选到一些正确的股票,但与稳健的 PMS 的纪律性一比,这些都不值一提。在感染坏疽并限制绩效之前,您将会补充优胜者并处理肉体创伤。您将成为更加纪律性的市场参与者。风险管理不是业务的一部分。它就是业务。投资组合经理不是从事挑选股票的业务。他们的业务是用他们要么挑选要么放弃的股票来管理风险。随着时间的推移,小的好处会复利,并使您与仍然相信挑选股票是成功关键的竞争对手有所区别。当您的投资组合管理成为您的钢铁侠装备时,您将与认为他们在交易一个系统的人竞争。

卖空是有风险的。市场不合作。然而,选择不学习卖空更加危险。你可能选择永远不参与卖空,但无论如何,学会卖空只会丰富你的技能库。我们真诚地希望这本书能引发关于卖空的讨论。这个领域已经被妖魔化和研究不足太久了。我们希望已经给予它应有的荣誉。

我们开始通过消除关于卖空的谬论,并解释为什么长期思维在卖空方面通常会失败。我们继续通过研究相对序列和制度定义来进行想法生成。这也涉及到头寸大小和风险管理。这本书的最后一部分远不止于长/短期投资组合的构建。它是关于设计一种投资者感兴趣的产品——无关联低波动回报——使用长/短期交易工具。

你将在附录,股票筛选中找到一个自动化的股票筛选工具,我们希望你会觉得有用!

附录:股票筛选

这个附录提供了一个股票筛选工具,它将让你把我们在本书中学到的一切付诸实践。它解决了市场参与者最迫切的问题:创意生成。我们将在标普 500 指数的所有成分股上建立一个筛选器。

事件的顺序如下:

  1. 从其维基百科页面下载所有当前标普 500 指数的成分股。

  2. 从 Yahoo Finance 批量下载 OHLCV 价格数据。我们将降低级别以处理每只股票。

  3. 计算调整后的相对系列。

  4. 计算制度——突破口、海龟、移动*均线(简单移动*均线SMA)和指数移动*均线EMA)),以及地板/天花板——在绝对和相对系列上。将有一个选项将每只股票保存为 CSV 文件。

  5. 创建包含每只股票最后一行的字典,并附加一个列表,从中我们将创建一个数据框。

  6. 总结制度方法并对数据框进行排序。你将有一个选项将这个最后一行数据框保存为 CSV 文件。

  7. 将包含维基百科信息的原始数据框与最后一行数据框合并。你将有一个选项将此数据框保存为 CSV 文件。

  8. 生成按行业和子行业分类的热力图。

  9. 如果你想要特别可视化任何股票,将会有一个单独的股票下载、处理和可视化模块在筛选的最后。

    你可以通过以下链接访问本章节所有图像的彩色版本:static.packt-cdn.com/downloads/9781801815192_ColorImages.pdf。你也可以通过本书的 GitHub 存储库访问本章的源代码:github.com/PacktPublishing/Algorithmic-Short-Selling-with-Python-Published-by-Packt

导入库

我们首先导入标准库。pathlib已经被注释掉了。如果你想要在计算机或服务器上的某个地方保存 CSV 文件,你可以使用诸如pathlibos之类的库。

# Appendix 
# Data manipulation
import pandas as pd
import numpy as np
from scipy.signal import *
# import pathlib
# Data download
import yfinance as yf
# Data visualisation
%matplotlib inline
import matplotlib.pyplot as plt 

当然,这是极具影响力的——我们将利用随后的片刻理智的消失迅速进行下一步。

定义函数

以下是本书中一直使用的函数。你可以在 GitHub 上找到完整版本。函数通常会以它们出现的章节为前缀。筛选将包括绝对和相对系列,因此我们需要相对函数。这将跟随经典的制度定义函数:

# CHAPTER 5: Regime Definition 
### RELATIVE
def relative(df,_o,_h,_l,_c, bm_df, bm_col, ccy_df, ccy_col, dgt, start, end,rebase=True):
    #### removed for brevity: check GitHub repo for full code ####
### RELATIVE ###
def lower_upper_OHLC(df,relative = False):
    if relative==True:
        rel = 'r'
    else:
        rel= ''      
    if 'Open' in df.columns:
        ohlc = [rel+'Open',rel+'High',rel+'Low',rel+'Close']       
    elif 'open' in df.columns:
        ohlc = [rel+'open',rel+'high',rel+'low',rel+'close']

    try:
        _o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
    except:
        _o=_h=_l=_c= np.nan
    return _o,_h,_l,_c

def  regime_args(df,lvl,relative= False):
    if ('Low' in df.columns) & (relative == False):
        reg_val = ['Lo1','Hi1','Lo'+str(lvl),'Hi'+str(lvl),'rg','clg','flr','rg_ch']
    elif ('low' in df.columns) & (relative == False):
        reg_val = ['lo1','hi1','lo'+str(lvl),'hi'+str(lvl),'rg','clg','flr','rg_ch']
    elif ('Low' in df.columns) & (relative == True):
        reg_val = ['rL1','rH1','rL'+str(lvl),'rH'+str(lvl),'rrg','rclg','rflr','rrg_ch']
    elif ('low' in df.columns) & (relative == True):
        reg_val = ['rl1','rh1','rl'+str(lvl),'rh'+str(lvl),'rrg','rclg','rflr','rrg_ch']

    try: 
        rt_lo,rt_hi,slo,shi,rg,clg,flr,rg_ch = [reg_val[s] for s in range(len(reg_val))]
    except:
        rt_lo=rt_hi=slo=shi=rg=clg=flr=rg_ch= np.nan
    return rt_lo,rt_hi,slo,shi,rg,clg,flr,rg_ch
# CHAPTER 5: Regime Definition 
#### regime_breakout(df,_h,_l,window) ####
def regime_breakout(df,_h,_l,window):
    #### removed for brevity: check GitHub repo for full code ####
#### turtle_trader(df, _h, _l, slow, fast) ####
#### removed for brevity: check GitHub repo for full code ####
#### regime_sma(df,_c,st,lt) ####
#### removed for brevity: check GitHub repo for full code ####
#### regime_ema(df,_c,st,lt) #### 

地板/天花板方法论计算量更大。因此,它需要有自己的沙盒:

# CHAPTER 5: Regime Definition 
#### hilo_alternation(hilo, dist= None, hurdle= None) ####
def hilo_alternation(hilo, dist= None, hurdle= None):
    i=0    
    while (np.sign(hilo.shift(1)) == np.sign(hilo)).any(): # runs until duplicates are eliminated
        #### removed for brevity: check GitHub repo for full code ####
#### historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None) #### 
def historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None):

    reduction = df[[_o,_h,_l,_c]].copy() 
    reduction['avg_px'] = round(reduction[[_h,_l,_c]].mean(axis=1),2)
    highs = reduction['avg_px'].values
    lows = - reduction['avg_px'].values
    reduction_target =  len(reduction) // 100
#     print(reduction_target )
#### removed for brevity: check GitHub repo for full code ####
#### cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo) ####
def cleanup_latest_swing(df, shi, slo, rt_hi, rt_lo): 
    '''
    removes false positives
    '''
    # latest swing
    shi_dt = df.loc[pd.notnull(df[shi]), shi].index[-1]
    s_hi = df.loc[pd.notnull(df[shi]), shi][-1]
    slo_dt = df.loc[pd.notnull(df[slo]), slo].index[-1] 
    s_lo = df.loc[pd.notnull(df[slo]), slo][-1] 
    len_shi_dt = len(df[:shi_dt])
    len_slo_dt = len(df[:slo_dt])

#### removed for brevity: check GitHub repo for full code ####
#### latest_swings(df, shi, slo, rt_hi, rt_lo, _h, _l, _c, _vol) ####
def latest_swing_variables(df, shi, slo, rt_hi, rt_lo, _h, _l, _c):
    '''
    Latest swings dates & values
    '''
    shi_dt = df.loc[pd.notnull(df[shi]), shi].index[-1]
    slo_dt = df.loc[pd.notnull(df[slo]), slo].index[-1]
    s_hi = df.loc[pd.notnull(df[shi]), shi][-1]
    s_lo = df.loc[pd.notnull(df[slo]), slo][-1]

    #### removed for brevity: check GitHub repo for full code ####
#### test_distance(ud, bs, hh_ll, vlty, dist_vol, dist_pct) ####
def test_distance(ud,bs, hh_ll, dist_vol, dist_pct): 

#### removed for brevity: check GitHub repo for full code ####
#### ATR ####
def average_true_range(df, _h, _l, _c, n):
    atr =  (df[_h].combine(df[_c].shift(), max) - df[_l].combine(df[_c].shift(), min)).rolling(window=n).mean()
    return atr
#### ATR ####
#### retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg) ####
def retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg):
    rt_sgmt = df.loc[hh_ll_dt:, _rt] 
    #### removed for brevity: check GitHub repo for full code ####
#### retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct) ####
def retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct):
    if _sign == 1: #
        retracement = df.loc[hh_ll_dt:, _c].min() - hh_ll
#### removed for brevity: check GitHub repo for full code ####
# CHAPTER 5: Regime Definition 
#### regime_floor_ceiling(df, hi,lo,cl, slo, shi,flr,clg,rg,rg_ch,stdev,threshold) ####
def regime_floor_ceiling(df, _h,_l,_c,slo, shi,flr,clg,rg,rg_ch,stdev,threshold):
#### removed for brevity: check GitHub repo for full code #### 

让我们将这段难以消化的代码分成两个简单的函数,swings()regime()。我们所需要做的就是传递relative参数以获取绝对或相对系列。

def swings(df,rel = False):
    _o,_h,_l,_c = lower_upper_OHLC(df,relative= False)
    if rel == True:
        df = relative(df=df,_o=_o,_h=_h,_l=_l,_c=_c, bm_df=bm_df, bm_col= bm_col, ccy_df=bm_df, 
                            ccy_col=ccy_col, dgt= dgt, start=start, end= end,rebase=True)
        _o,_h,_l,_c = lower_upper_OHLC(df,relative= True)    
        rt_lo,rt_hi,slo,shi,rg,clg,flr,rg_ch = regime_args(df,lvl,relative= True)
    else :
        rt_lo,rt_hi,slo,shi,rg,clg,flr,rg_ch = regime_args(df,lvl,relative= False)
    df= historical_swings(df,_o,_h,_l,_c, dist= None, hurdle= None)
    df= cleanup_latest_swing(df,shi,slo,rt_hi,rt_lo)
    ud, bs, bs_dt, _rt, _swg, hh_ll, hh_ll_dt = latest_swing_variables(df, shi,slo,rt_hi,rt_lo,_h,_l, _c)
    vlty = round(average_true_range(df,_h,_l,_c, n= vlty_n)[hh_ll_dt],dgt)
    dist_vol = d_vol * vlty
    _sign = test_distance(ud,bs, hh_ll, dist_vol, dist_pct)
    df = retest_swing(df, _sign, _rt, hh_ll_dt, hh_ll, _c, _swg)
    retrace_vol = r_vol * vlty
    df = retracement_swing(df, _sign, _swg, _c, hh_ll_dt, hh_ll, vlty, retrace_vol, retrace_pct)

    return df

def regime(df,lvl,rel=False):   
    _o,_h,_l,_c = lower_upper_OHLC(df,relative= rel)    
    rt_lo,rt_hi,slo,shi,rg,clg,flr,rg_ch = regime_args(df,lvl,relative= rel)
    stdev = df[_c].rolling(vlty_n).std(ddof=0)
    df = regime_floor_ceiling(df,_h,_l,_c,slo, shi,flr,clg,rg,rg_ch,stdev,threshold) 

    return df
# df[rg+'_no_fill'] = df[rg]
    return df 

这个筛选也允许对个别股票进行精彩的可视化。 要实现这一点,请运行 graph_regime_combo() 函数:

# CHAPTER 5: Regime Definition 
### Graph Regimes ###
def graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,
                       ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi):

    '''
    https://www.color-hex.com/color-names.html
    ticker,df,_c: _c is closing price
    rg: regime -1/0/1 using floor/ceiling method
    lo,hi: small, noisy highs/lows
    slo,shi: swing lows/highs
    clg,flr: ceiling/floor

    rg_ch: regime change base
    ma_st,ma_mt,ma_lt: moving averages ST/MT/LT
    lt_lo,lt_hi: range breakout High/Low LT 
    st_lo,st_hi: range breakout High/Low ST 
    '''
#### removed for brevity: check GitHub repo for full code #### 

下面的两个函数尚未在书中提及。 使用它们,我们需要提取单个股票数据并将其聚合成一个数据框。 yf_droplevel() 函数从 batch_download 中获取多指数数据框的单个代码的 OHLC 列,并创建一个 OHLCV 数据框:

def yf_droplevel(batch_download,ticker):
    df = batch_download.iloc[:, batch_download.columns.get_level_values(1)==ticker]
    df.columns = df.columns.droplevel(1)
    df = df.dropna()
    return df 

此函数插入到一个循环中,该循环将运行 batch_download 的长度。 last_row_dictionary(df) 函数将数据框中的最后一行创建为一个字典:

def last_row_dictionary(df):    
    df_cols = list(df.columns)
    col_dict = {'Symbol':str.upper(ticker),'date':df.index.max().strftime('%Y%m%d')}
    for i, col_name in enumerate(df_cols):
        if pd.isnull(df.iloc[-1,i]):
            try:
                last_index = df[pd.notnull(df.iloc[:,i])].index[-1]
                len_last_index = len(df[:last_index]) - 1
                col_dict.update({col_name + '_dt': last_index.strftime('%Y%m%d')})
                col_dict.update({col_name : df.iloc[len_last_index,i]})
            except:
                col_dict.update({col_name + '_dt':np.nan})
                col_dict.update({col_name : np.nan})
        else:
            col_dict.update({col_name : df.iloc[-1,i]})
    return col_dict 

首先,我们列出列。 其次,我们用代码和日期填充它们,使每一行都能唯一识别。 第三,我们使用 enumerate 迭代返回索引和列名。 如果最后一行包含缺失值,我们将向列名添加 _dt 并查找最后一个出现的索引。 如果最后一行包含值,我们只需将列名添加为键和值。

这个字典将附加一个最后一行字典的列表。 然后,我们将从此列表创建一个数据框。 另一种方法是为每只股票创建一个数据框并进行追加,这种方法效果很好,但稍微耗时一些。

控制面板

在笔记本中散布的变量是错误的来源。 在处理数据之前,所有参数、变量、网站、列表和布尔值都集中在一个地方。 这是您可以在其中调整设置的地方:

website = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
params = ['2014-12-31', None, 63, 0.05, 0.05, 1.5, 2,5,2.5,3]
start,end,vlty_n,dist_pct,retrace_pct,threshold,dgt,d_vol,r_vol,lvl= [params[h] for h in range(len(params))]
rel_var = ['^GSPC','SP500', 'USD']
bm_ticker, bm_col, ccy_col = [rel_var[h] for h in range(len(rel_var))]
window = 100
st= fast = 50
lt = slow = 200
batch_size = 20
show_batch = True
save_ticker_df = False
save_last_row_df = False
save_regime_df = False
web_df_cols = ['Symbol','Security','GICS Sector','GICS Sub-Industry']
regime_cols = ['rg','rrg',
    'smaC'+str(st)+str(lt),'smar'+str(st)+str(lt), 'boHL'+str(slow),
'borr'+str(slow),'ttH'+str(fast)+'L'+str(slow),'ttr'+str(fast)+'r'+str(slow)]
swings_cols = ['flr_dt','flr','clg_dt', 'clg', 'rg_ch', 
    'Hi'+str(lvl)+'_dt','Hi'+str(lvl),'Lo'+str(lvl)+'_dt','Lo'+str(lvl),
      'rflr_dt', 'rflr', 'rclg_dt', 'rclg', 'rrg_ch',
    'rH'+str(lvl)+'_dt','rH'+str(lvl),'rL'+str(lvl)+'_dt','rL'+str(lvl) ]
symbol_cols = ['Symbol','date','Close']
last_row_df_cols = symbol_cols+['score']+regime_cols+swings_cols 

我们使用的网站是 S&P500 的维基百科网页。 参数如下:

  • start: yfinance 下载开始日期

  • end: yfinance 下载结束日期

  • vlty_n: 持续时间,用于*均真实范围和标准偏差计算

  • dist_pct: test_distance() 函数中的变量

  • retrace_pct: retracement_swing() 函数中的变量

  • threshold: 用于地板/天花板制度定义的波动性单位

  • dgt: round() 函数中的小数位数

  • d_vol: test_distance() 函数中的波动性单位

  • r_vol: retracement_swing() 函数中的变量

  • lvl: 指示应使用哪些摆动水*来计算制度定义—Hi2/Lo2 还是 Hi3/Lo3

rel_var 参数解释如下:

  • bm_ticker: 基准的 Yahoo Finance 代码

  • bm_col: 基准列的名称

  • ccy_col: 货币名称

  • windowstfastltslow: 突破和移动*均值的变量

  • batch_size: 从 yfinance 下载的批量大小

  • show_batch: 布尔值,显示下载的股票

  • save_ticker_df: 布尔值,提供保存个别股票数据框的选项

  • save_last_row_df: 布尔值,提供保存最后一行数据框的选项

  • save_regime_df: 布尔值,提供保存最后一行数据框的选项

  • web_df_cols: 要从原始维基百科数据框中显示的列

  • regime_cols: 重新排序的制度定义列

  • swings_cols: 地板/天花板列

  • symbol_cols:描述性字段,SymboldateClose

  • last_row_df_cols:最后一行数据帧有 50 多列。 这将列数减少到最小。

数据下载和处理

我们将从维基百科下载股票列表开始。 这使用了我们在第四章中看到的强大的pd.read_html方法,Long/Short Methodologies: Absolute and Relative

web_df = pd.read_html(website)[0]
tickers_list =  list(web_df['Symbol'])
tickers_list = tickers_list[:]
print('tickers_list',len(tickers_list))
web_df.head() 

tickers_list可以通过填写tickers_list[:]的括号部分来截断。

现在,这就是发生动作的地方。 引擎室中有几个嵌套的循环。

  1. 批量下载:这是高级别循环。 OHLCV 以一系列批次的多索引数据帧下载。 迭代次数是股票清单长度和批量大小的函数。 505 个组成部分除以 20 的批量大小是 26(最后一批为 6 个股票长)。

  2. 删除级别循环:这将多索引数据帧分解为单个股票 OHLCV 数据帧。 迭代次数等于批量大小。 制度在此级别处理。

  3. 绝对/相对处理:有 2 个通过。 第一遍处理绝对系列的数据。 变量在最后重置为相对系列,然后在第二遍中相应处理。 有一个选项将股票信息保存为 CSV 文件。 最后一行字典在第二遍结束时创建。

接下来,让我们一步一步地进行过程:

  1. 基准下载收盘价和货币调整。 这需要执行一次,因此它放在序列的开头。

  2. 数据帧和列表实例化。

  3. 循环大小:循环tickers_list所需的迭代次数。

  4. 外循环:批量下载:

    1. m,n:沿着batch_list的索引。

    2. batch_download:使用yfinance下载。

    3. 打印批次股票,如果要查看股票名称,则带有布尔值

    4. 下载批量。

    5. try/except:附加失败列表。

  5. 第二个循环:单股票删除级别循环:

    1. 降级到股票级别。

    2. 计算摆动和制度:abs/rel

  6. 第三个循环:绝对/相对系列:

    1. 在绝对系列中处理制度。

    2. 重置变量为相对系列并第二次处理制度。

  7. 提供布尔值以提供save_ticker_df选项。

  8. 使用最后一行值创建字典。

  9. 附加字典行的列表。

  10. 从字典创建数据帧last_row_df

  11. score列:绝对和相对制度方法的横向求和。

  12. last_row_dfweb_df合并。

  13. 布尔值save_regime_df

让我们发布代码,然后进行进一步的解释:

# Appendix: The Engine Room

bm_df = pd.DataFrame()
bm_df[bm_col] = round(yf.download(tickers= bm_ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None)['Close'],dgt)
bm_df[ccy_col] = 1
print('benchmark',bm_df.tail(1))

regime_df = pd.DataFrame()
last_row_df = pd.DataFrame()
last_row_list = []
failed = []

loop_size = int(len(tickers_list) // batch_size) + 2
for t in range(1,loop_size): 
    m = (t - 1) * batch_size
    n = t * batch_size
    batch_list = tickers_list[m:n]
    if show_batch:
        print(batch_list,m,n)

    try:
        batch_download = round(yf.download(tickers= batch_list,start= start, end = end, 
                            interval = "1d",group_by = 'column',auto_adjust = True, 
                                  prepost = True, treads = True, proxy = None),dgt)        

        for flat, ticker in enumerate(batch_list):
            df = yf_droplevel(batch_download,ticker)           
            df = swings(df,rel = False)
            df = regime(df,lvl = 3,rel = False)
            df = swings(df,rel = True)
            df = regime(df,lvl = 3,rel= True)            
            _o,_h,_l,_c = lower_upper_OHLC(df,relative = False)

            for a in range(2): 
                df['sma'+str(_c)[:1]+str(st)+str(lt)] = regime_sma(df,_c,st,lt)
                df['bo'+str(_h)[:1]+str(_l)[:1]+ str(slow)] = regime_breakout(df,_h,_l,window)
                df['tt'+str(_h)[:1]+str(fast)+str(_l)[:1]+ str(slow)] = turtle_trader(df, _h, _l, slow, fast)
                _o,_h,_l,_c = lower_upper_OHLC(df,relative = True)                
            try: 
                last_row_list.append(last_row_dictionary(df))
            except:
                failed.append(ticker) 
    except:
        failed.append(ticker)
last_row_df = pd.DataFrame.from_dict(last_row_list)

if save_last_row_df:
    last_row_df.to_csv('last_row_df_'+ str(last_row_df['date'].max())+'.csv', date_format='%Y%m%d')
print('failed',failed)

last_row_df['score']= last_row_df[regime_cols].sum(axis=1)
regime_df = web_df[web_df_cols].set_index('Symbol').join(
    last_row_df[last_row_df_cols].set_index('Symbol'), how='inner').sort_values(by='score')

if save_regime_df:
    regime_df.to_csv('regime_df_'+ str(last_row_df['date'].max())+'.csv', date_format='%Y%m%d') 

last_row_list.append(last_row_dictionary(df)) 在第三次循环结束时发生,一旦每个个股都被完全处理完毕。这个列表会自动更新每个个股和每个批次。三次循环完成后,我们使用 pd.DataFrame.from_dict(last_row_list) 从这个字典列表创建 last_row_df 数据帧。将字典列表创建为数据帧并将其合并的过程比直接将其附加到数据帧稍快一些。score 列是所有区域方法的横向总和。然后按 score 按升序对最后一行数据帧进行排序。有保存日期版本的选项。regime 数据帧是通过将维基百科网络数据帧和最后一行数据帧连接而创建的。请注意,Symbol 列被设置为 index。同样,有保存日期版本的选项。

接下来,让我们用几个热图来可视化市场的情况。

热图

维基百科页面展示了 全球行业分类标准GICS)部门和子行业的结构。我们将按以下方式汇总数据:

  • 部门,用于自上而下的视角

  • 子行业,用于自下而上的视角

  • 最后,部门 子行业,以在每个部门内选择赢家和输家。

我们使用 .groupby() 方法并按 score 排序。然后我们使用 Styler 构造函数 .style.background_gradient() 根据数字绘制市场:

groupby_cols = ['score'] + regime_cols
sort_key = ['GICS Sector']
regime_df.groupby(sort_key)[groupby_cols].mean().sort_values(
    by= 'score').style.background_gradient(
    subset= groupby_cols,cmap= 'RdYlGn').format('{:.1g}') 

热力图覆盖了所有区域方法,包括绝对和相对:

  • score:股票级别所有方法的横向总和。

  • rg:绝对的底部/顶部区域。

  • rrg:相对的底部/顶部区域。

  • smaC50200:移动*均线交叉 ST/LT 绝对。

  • smar50200:移动*均线交叉 ST/LT 相对。

  • bohl200:范围突破(200 天)。

  • ttH50L200:绝对的对于菜鸟的乌龟 50/200(快速/慢速)。

  • ttr50r200:相对的对于菜鸟的乌龟 50/200(快速/慢速)。

让我们看看它是什么样子的:

图形用户界面,描述自动生成,置信度中等

图 1:行业水*的区域分数热图

部门热图为市场提供了一个鸟瞰图。高度杠杆的部门,如金融、房地产和科技仍然处于金字塔顶部。与此同时,消费品行业等防御性行业落后。在撰写本文时,这个牛市仍然十分活跃。实际上就是这么简单。

然后我们深入到子行业:

sort_key = ['GICS Sub-Industry']
regime_df.groupby(sort_key)[groupby_cols].mean().sort_values(
    by= 'score').style.background_gradient(
    subset= groupby_cols,cmap= 'RdYlGn').format('{:.1g}') 

这给了我们市场的一个像素化图片,较差表现的子行业位于顶部:

图形用户界面,应用程序描述自动生成

图 2:区域分数的子行业水*

标普 500 指数是一个广泛而深入的指数。 市场的这种细粒度图像显示了每个子行业目前的状况。 特别关注绝对/相对二元性。 记住,相对表现领先于绝对表现。 这就是您如何捕捉拐点并相应地建立或退出仓位,并等待其他人群的到来的方式。

这个详细的图像是信息与决策的经典例子。 这个热图将使您了解市场的情况。 但是,它的格式不够高效,不能让您根据信息采取行动。

这将我们带到最终的排序,按部门和子行业。

sort_key = ['GICS Sector','GICS Sub-Industry']
regime_df.groupby(sort_key)[groupby_cols].mean().sort_values(
    by= ['GICS Sector','score']).style.background_gradient(
    subset= groupby_cols,cmap= 'RdYlGn').format('{:.1g}') 

这会生成一个热图,其中子行业按其行业内的升序排序。 与此同时,部门按字母顺序分类。

图表,树状图表 自动生成的描述

图 3:部门和子行业级别的热图

这个最终的热图提供了可行的信息。 子行业按其部门内的升序排名。 这允许在表现不佳者和表现良好者之间进行套利。 在不同部门和时间内重复这个过程,您将顺利地遵循部门轮换的实质。 这就是长/短 2.0 相对方法的本质。

个体流程

一旦筛选完成,您可能希望查看列表中的一些股票。 因此,笔记本的其余部分是关于在个别股票水*上进行数据可视化的。 输入一个股票代码,例如,ticker = 'FMC'

bm_ticker= '^GSPC'
bm_df = pd.DataFrame()
bm_df[bm_col] = round(yf.download(tickers= bm_ticker,start= start, end = end,interval = "1d",
                 group_by = 'column',auto_adjust = True, prepost = True, 
                 treads = True, proxy = None)['Close'],dgt)
bm_df[ccy_col] = 1
ticker = 'FMC'
lvl = 2 # Try different levels to see

df = round(yf.download(tickers= ticker,start= start, end = end,    interval = "1d", group_by = 'column',auto_adjust = True,     prepost = True, treads = True, proxy = None),dgt)

df = swings(df,rel = False)
df = regime(df,lvl = 2,rel = False) # Try different lvl values (1-3) to vary absolute sensitivity
df = swings(df,rel = True) # Try different lvl values (1-3) to vary relative sensitivity
df = regime(df,lvl = 2,rel= True)
_o,_h,_l,_c = lower_upper_OHLC(df,relative = False)

for a in range(2):    
    df['sma'+str(_c)[:1]+str(st)+str(lt)] = regime_sma(df,_c,st,lt)
    df['bo'+str(_h)[:1]+str(_l)[:1]+ str(slow)] = regime_breakout(df,_h,_l,window)
    df['tt'+str(_h)[:1]+str(fast)+str(_l)[:1]+ str(slow)] = turtle_trader(df, _h, _l, slow, fast)
    _o,_h,_l,_c = lower_upper_OHLC(df,relative = True)
df[['Close','rClose']].plot(figsize=(20,5),style=['k','grey'],
                           title = str.upper(ticker)+ ' Relative &                              Absolute') 

这将打印出类似以下图表的内容:

图 4:FMC 收盘价的绝对和相对系列

以下部分将数据绘制成三个图表:

# CHAPTER 5: Regime Definition 
plot_abs_cols = ['Close','Hi'+str(lvl), 'clg','flr','rg_ch','rg']
# plot_abs_cols = ['Close','Hi2', 'Lo2','clg','flr','rg_ch','rg']
plot_abs_style = ['k', 'ro', 'go', 'kv', 'k^','b:','b--']
y2_abs = ['rg']
plot_rel_cols = ['rClose','rH'+str(lvl), 'rL'+str(lvl), 'rclg','rflr','rrg_ch','rrg']
# plot_rel_cols = ['rClose','rH2', 'rL2','rclg','rflr','rrg_ch','rrg']
plot_rel_style = ['grey', 'ro', 'go', 'kv', 'k^','m:','m--']
y2_rel = ['rrg']
df[plot_abs_cols].plot(secondary_y= y2_abs,figsize=(20,8),
            title = str.upper(ticker)+ ' Absolute',# grid=True,
            style=plot_abs_style)
df[plot_rel_cols].plot(secondary_y=y2_rel,figsize=(20,8),
            title = str.upper(ticker)+ ' Relative',# grid=True,
            style=plot_rel_style)
df[plot_rel_cols + plot_abs_cols].plot(secondary_y=y2_rel + y2_abs,    figsize=(20,8), title = str.upper(ticker)+ ' Relative & Absolute',    # grid=True,
    style=plot_rel_style + plot_abs_style) 

这将创建三个图表:绝对、相对和绝对与相对结合。 红/绿色的点是波动。 水*线是制度变革波动。 请注意,以下图表是在绝对和相对系列的 lvl 设置为 2 的情况下生成的。 您可以通过在绝对系列的 df = regime(df,lvl = 2,rel = False) 行和相对系列的 df = regime(df,lvl = 2,rel = True) 行中更改此值来增加或减少任一系列的灵敏度。

图 5:绝对图表,显示有虚线的底部/顶部制度

图 6:相对图表,显示有虚线的底部/顶部制度。 红/绿色的点是波动

图 7:具有底部/顶部制度的绝对和相对图表

下一段代码块使用 graph_regime_combo() 进行美观的视觉呈现。 首先,这是绝对系列,然后是相对系列:

# CHAPTER 5: Regime Definition 
ohlc = ['Open','High','Low','Close']
_o,_h,_l,_c = [ohlc[h] for h in range(len(ohlc))]
# ma_st = ma_mt = ma_lt = lt_lo = lt_hi = st_lo = st_hi = 0
mav = [fast, slow, 200]
ma_st,ma_mt,ma_lt = [df[_c].rolling(mav[t]).mean() for t in range(len(mav))]
bo = [fast, slow]
st_lo,lt_lo = [df[_l].rolling(bo[t]).min() for t in range(len(bo))]
st_hi,lt_hi = [df[_h].rolling(bo[t]).max() for t in range(len(bo))]
rg_combo = ['Close','rg','Lo3','Hi3','Lo3','Hi3','clg','flr','rg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch =[rg_combo[r] for r in range(len(rg_combo)) ]
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi)
rohlc = ['rOpen','rHigh','rLow','rClose']
_o,_h,_l,_c = [rohlc[h] for h in range(len(rohlc)) ]

mav = [fast, slow, 200]
ma_st,ma_mt,ma_lt = [df[_c].rolling(mav[t]).mean() for t in range(len(mav))]
bo = [fast, slow]
st_lo,lt_lo = [df[_l].rolling(bo[t]).min() for t in range(len(bo))]
st_hi,lt_hi = [df[_h].rolling(bo[t]).max() for t in range(len(bo))]
rrg_combo = ['rClose','rrg','rL3','rH3','rL3','rH3','rclg','rflr','rrg_ch']
_c,rg,lo,hi,slo,shi,clg,flr,rg_ch =[rrg_combo[r] for r in range(len(rrg_combo)) ]
graph_regime_combo(ticker,df,_c,rg,lo,hi,slo,shi,clg,flr,rg_ch,ma_st,ma_mt,ma_lt,lt_lo,lt_hi,st_lo,st_hi) 

这将生成以下两个图表。

图 8:具有多种制度方法的绝对图表

图 9:具有多种制度方法的相对图表

这是本书的结尾,也是你踏上空头交易广阔荒野的征程的开始。你现在拥有一张地图,将帮助你在空头市场的惊涛骇浪中航行。

作为告别的话,我们无情的行业忠实地遵循一条法则:供需关系。在长/空头交易中,长期股票选择者充足,而熟练的空头卖家却严重短缺。

当市场走低时,那些挺身而出的人,才会脱颖而出。

posted @ 2024-05-09 17:01  绝不原创的飞龙  阅读(30)  评论(0编辑  收藏  举报