作者 | 元宵大师 责编 | 胡巍巍 剖析斐波那契数列 对于斐波那契数列相信大家并不陌生,它指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144、233…………这个数列究竟蕴含着什么秘密呢?我们从以下三个问题展开对斐波那契数列的剖析: (1) 斐波那契数列是怎么由来的? 斐波那契数列是由意大利中世纪数学家斐波那契(Fibonacci,公元1175-1240)在他1202年著作的《算盘书》(Liber Abaci)中以兔子繁殖为例子所引出的。 在书中提出了一个有趣的问题:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生一对小兔,一年内没有发生死亡,那么一对刚出生的兔子,在一年内繁殖成多少对兔子? 依照假定条件计算,第一个月是一对兔子,第二个月长成了大兔,第三个月生下一对小兔总共由两对兔子…… 在并不知晓斐波那契数列隐含的规律情况下,我们手动推算得到了一年内兔子繁殖的情况,如下图所示: 由该繁衍规律得到的每个月兔子的数量组成了斐波那契数列,因此也称为“兔子数列”。 发生在18世纪中期的澳大利亚野兔成灾的故事体现了真实版的“兔子数列”惊人的增长速度。 当时英国殖民者为了满足自己的狩猎爱好把欧洲野兔引进了澳大利亚,由于澳大利亚气候温暖、牧草丰富,为兔子提供了良好的生存条件,加上澳大利亚本土缺乏猛禽、黄鼠狼等兔子的天敌,兔子开启了斐波那契数列式的增长,当时澳大利亚的生态遭到了严重破坏,继而开始了人兔大战……接下来让我们逐步揭开斐波那契数列的秘密。 (2) 斐波那契数列的规律是什么? 从[0、1、1、2、3、5、8、13、21、34、55、89、144、233…………]这个序列中可以发现,第一个元素为0,第二个元素为1,之后的每一个元素为之前两个元素之和。在数学上,我们可以用递归的方法来定义斐波纳契数列的生成规律,如下所示:
(3) 斐波那契数列神奇之处在哪? 斐波那契数列存在许多神奇的性质,我们不妨对斐波那契数列中相邻的两个数求商值。当前一个数值除以后一个数值时可以得到以下的结果: 0 ÷ 1 = 0 1 ÷ 1 = 1 1 ÷ 2 = 0.5 2 ÷ 3 = 0.6666… 3 ÷ 5 = 0.6 5 ÷ 8 = 0.625 8 ÷ 13 = 0.615… 13 ÷ 21 = 0.619… 21 ÷ 34 = 0.617… 34 ÷ 55 = 0.618… 55 ÷ 89 = 0.617… 89 ÷ 144 = 0.618… 144 ÷ 233 = 0.618… …… 我们注意到从21除以34开始以至于到数列的无穷大,商值是趋于0.618的一个无理数! 反过来当后一个数值除以其前面的数值时得到的结果如下所示: 1 ÷ 0 = 0 1 ÷ 1 = 1 2 ÷ 1 = 2 3 ÷ 2 = 1.5 5 ÷ 3 = 1.67 8 ÷ 5 = 1.6 13 ÷ 8 = 1.625 21 ÷ 13 = 1.615… 34 ÷ 21 = 1.619… 55 ÷ 34 = 1.618… 89 ÷ 55 = 1.618… 144 ÷ 89 = 1.618… 相应的从34除以21开始直到数列无穷大,商值是趋于1.618的一个无理数!0.618与1.618彼此出奇的互为倒数,并且0.618这个数值正是有名的“黄金分割”比例!这也是斐波那契数列又称为黄金分割数列的原因。 实际上黄金分割的提出要远早于斐波那契数列。假设线段总长为1,在线段上找到一个黄金分割点,将线段分割为A和B两部分,B的长度为x,A的长度为1-x,如下图所示: A与B的长度之比等于B与全长的比,这个比例就为黄金分割,比例关系如下所示: 对该公式进行转换,并求出x值,如下所示: 于是B与全长的比为0.618,B与A的长度比为1.618,实际上它们指的是同样线段的黄金分割比例。 Python验证数列的神奇 对于枯燥而繁琐的计算类工作理应交给Python来做!上文提到斐波纳契数列的生成规律是由递归方法来定义的,因此用Python递归函数生成数列会更直观、更容易理解。代码如下所示:
分别绘制出包含10项和30项数值的斐波那契数列增长曲线,如下图所示。 绘制斐波那契数列增长曲线代码如下所示:
从图中斐波那契数列增长形式上可以看出,数列在初期增长缓慢,之后呈现出以1.618为底数的指数增长速度。 虽然使用递归函数生成数列优点是定义简单,逻辑清晰,不过缺点是实现的效率极低,并且深层次递归调用时会导致栈溢出。 我们采用Python内置time模块来测试下递归函数生成30项斐波那契数列所开销时间。分别在代码的开始和结束处添加time.perf_counter函数,用于返回系统的运行时间,由于返回值的基准点是未定义的,所以只有连续调用的结果之差才是有效的代码开销时间。我们测得的执行时间为2.918秒。代码如下所示:
理论上,所有的递归函数都可以写成循环的方式,虽然循环的逻辑不如递归清晰,但在执行效率上循环优势明显,改用循环方式后所测得的执行时间仅仅为16.44微秒。代码如下所示:
在使用循环方式生成斐波那契数列时,必须要用列表来存储每次计算得到的数值,为了让代码优雅起来,我们可以使用生成器来优化。所谓生成器其实是一种特殊的迭代器,内部支持了迭代器协议。 Python中提供生成器函数和生成器表达式两种方式实现生成器,每次请求返回一个结果,不需要一次性构建一个结果列表,节省了内存空间。此处我们使用生成器函数方式实现生成器,这种方式编写为常规的def语句,使用yield语句一次返回一个结果,在每个结果之间挂起和继续它们的状态。代码如下所示:
上文还提到了斐波那契数列前一个数值除以后一个数值时,随着数列的增长,商值为是趋于0.618的一个无理数。接下来我们用Python验证一下。实现代码如下所示:
我们得到了斐波那契数列的Fn/Fn+1的前100项的结果,如下图所示。从图中可知,第八项与第九项的比值开始,之后的数值都趋于0.618左右。 因此再一次验证得到斐波那契数列是近似指数增长的形式,为了更确切的说明这个问题,我们看一下由数学家比内建立的斐波那契数列的通项公式,如下所示: 由通项公式计算Fn/Fn+1的结果依然是0.618,如下所示: 黄金分割率分析股价 斐波那契数列是大自然的一个基本属性,尤其是数列中的黄金分割比例部分,它出现在绘画、雕塑、建筑等多个领域,人们不约而同地认为黄金分割比例是最完美的。 比如“断臂的维纳斯”雕塑,身高2.02米,她的肚脐正是黄金分割点,肚脐以上部分和肚脐以下部分之比接近于0.618。可见黄金分割比例是作用在人们潜意识中的一种客观规律,有着极强的自然属性,当然也包括在股市的分析中:股价一直遵循着高低相间的运行规律。 当股价走势出现反转时极有可能在黄金分割比例0.382、 0.618上遇到暂时的阻力或支撑,因此通过黄金分割比例寻找出上涨/下跌趋势中的压力位和支撑位,有助于交易者更好地判断“入场”和“出场”的时机。 接下来以股票“新希望”的历史数据为例,寻找股价的支撑位和压力位。“新希望” 2019年1月至2019年6月的走势图如下所示: 通常股价的拉升不会一步到位,大多采用螺旋式上涨,也就是说在新的上涨前,要有一波回撤,洗去浮动的筹码来蓄势待发,而回撤的幅度恰好符合黄金分割的比例0.618。 “新希望”这半年期间股价呈上涨趋势,中途有几次短暂的回撤走势,我们用黄金分割比例来计算下回撤的位置。计算公式为(最大值-最小值)*黄金分割比例+最小值,实现方法如下所示:
接下来验证黄金分割比例判断支撑/阻力位的有效性,如下图所示,第一轮回撤位置正好在黄金分割率0.618所处位置,即11.61。 总结 本文以股价分析为应用场景介绍了斐波那契数列的神奇特征,尽管斐波那契的黄金分割线可以帮助交易者提高判断支撑位或阻力位的成功率。 但和其他的技术分析工具一样,它也存在一定的局限性,比如单纯以波段高点和波段低点的差值作为基准这个方式,在波动较大或者区间震荡持续较久的行情下可靠性会降低,改进的方法可以将股价按序列值大小排序,取黄金分割比例所对应位置上的序列值,这样可靠性会更高。 作者简介:元宵大师,Python高级工程师,致力于推动人工智能、大数据分析在金融量化交易领域中的应用。欢迎大家关注我的个人公众号《元宵大师带你用Python量化交易》。 |
|
来自: 山峰云绕 > 《Python代码知识游戏黑客编程与英语》