IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 信号越多越好?随机相对强弱指数 vs. 相对强弱指数 -> 正文阅读

[大数据]信号越多越好?随机相对强弱指数 vs. 相对强弱指数

????????在我之前的文章“移动平均函数对 RSI 交叉策略回测结果的显着影响”中,我们观察到原作者 J. Welless Wilder 相对强弱指数指标在中等长度的时间段内很难产生信号(实验大约使用四个月的有效数据)。 我们发现使用 14 天周期的简单移动平均线 (SMA) 来计算 相对强弱指数是一个不错的选择。 另外,选择 Wilder相对强弱指数在交叉值 35 与 65 也是一个不错的选择。

????????Tushar Chande 和 Stanley Kroll 于 1994 年开发了随机相对强弱指数 (Stochastic RSI),以提高产生超买和超卖信号的机会。和相对强弱指数一样,随机相对强弱指数也是一个震荡指标,它的数值在 0 到 1 之间。基本上,它是相对强弱指数的衍生物,用来衡量相对强弱指数的强弱程度。 然而,随机相对强弱指数的值变化非常迅速,并且经常达到末端值。 因此,许多使用者建议使用移动平均功能进行平滑,以减少市场噪音及更好地揭示趋势。并且对这两个指标使用的适当时间,给出了一个共同的结论。 当市场持平或波动时,随机相对强弱指数会产生良好的结果,而相对强弱指数则在趋势市场中的表现要好得多。

????????随机相对强弱指数的方程可以写成如下,其中 RSImax 和 RSImin 是 n个数据期间的最大和最小的随机相对强弱指数。 默认情况下,n 为 14。

????????使用图表来观察值的变化要容易得多。 在本文中,我们尝试将回溯测试应用于免佣金交易所交易基金 (ETF),并专注于将 Elasticsearch 作为分析工具。 下面的例子随机选择了“Fidelity International Multifactor ETF”。 其股票代码为FDEV。 另外随机抽取23只ETF运行,最终结果将在稍后展示。 数据选自投资者交易所 IEX 提供的 2021-01-01 和 2021-09-30 之间的时间范围。 但是,实验期仅从 2021-05-01 到 2021-09-30。 原因是需要足够数量的数据点来计算第一个有效相对强弱指数值,尤其是使用指数加权移动平均线时。 建议快速浏览一下我之前的文章,对通过Elasticsearch实现相对强弱指数的细节有一个基本的了解。

????????以下第一个图表显示Wilder的 相对强弱指数RSI(用蓝线绘制)对收盘价的变化是不敏感的,在测试期结束之前没有产生高于 70 或低于 30 的信号。 另一方面,随机相对强弱指数StochRSI(用红线绘制)似乎过于敏感,并且会产生大量信号。 对于随机相对强弱指数,交叉值为 0.8 和 0.2。?

?????????第二张图表显示,使用 7 天简单移动平均来平滑 StochRSI (用午夜蓝线绘制),似乎生成了合理数量的信号。 显然,平滑后的信号是滞后的,不像原始信号那样清晰和具代表性。

?????????以下先介绍一下使用Python和Elasticsearch的实现,后面再展示回测结果。 假设有一个填充数据的 Elasticsearch 索引,其数据映射显示在 Gitee Backtest_SRSI?的开源项目中。 以下步骤演示了 REST API 请求正文的代码。

通过搜索操作收集所有相关文档

使用带有必要条件(must)子句的布林查询(bool query)来收集股票代码为FDEV和日期从2021年05月01日到2021年09月30日的文档。 由于需要计算滑动窗口,因此增加了4个月的数据(从2021年01月01日到2021年04月30日)。

{
    "query": {
        "bool": {
		     "must": [
		         {"range": {"date": {"gte": "2021-01-01", "lte": "2021-09-30"}}},
		         {"term": {"symbol": "FDEV"}}
		     ]
		}
	},

从交易日选择文件

使用名为Backtest_SRSI日期直方图(date_histogram)存储桶聚合,并配合参数field(字段)为date和interval(间隔)为 1d(1天)。由于没有内插数据,为了过滤非交易日(空桶),使用名为 SDaily 的“bucket_selector”聚合来选择文档计数(_count)大于 0 的桶。

    "aggs": {
        "Backtest_RSIs": {
            "date_histogram": {
                "field": "date",
                "interval": "1d",
                "format": "yyyy-MM-dd"
            },
             "SDaily": {
                 "bucket_selector": {
                     "buckets_path": {"count":"_count"},
                         "script": "params.count > 0"
                }
            },

提取桶的日期

由于额外的数据,后续操作需要稍后过滤掉超出范围的部分。 名为“DateStr”的“min”聚合用于获取存储桶的日期。 在 Elasticsearch 服务器中,日期以纪元时间存储。 时间单位为毫秒,时区为UTC。

                "DateStr": {
                    "min": {"field": "date"}
                },

提取每日的收盘价

由于子聚合使用管道(pipeline)聚合而无法直接采用文档字段,所以额外使用 “平均”聚合,名为 Close,用于检索收盘价。

            "aggs": {
                "Close": {
                    "avg": {"field": "close"}
                },

计算连续两个交易日收盘价的差值

使用名为DClose的导数(derivative)聚合,并配合参数buckets_path指定Close聚合的值来确定它与前一个时间戳的值。

                "DClose": {
                    "derivative": {"buckets_path": "Close"}
                },

确定连续两个交易日收盘价差值是收益还是损失

使用两个“bucket_script”聚合,命名为 Gain 和 Loss,并使用参数“buckets_path”指定 DClose 聚合的结果来确定值。 两个值都必须是正值或为零值。

            "Gain": {
                "bucket_script": {
                    "buckets_path": {DClose": "DClose"},
                    "script": "(params.DClose > 0) ? params.DClose : 0"
                }
            }, 
            "Loss": {
                "bucket_script": {
                    "buckets_path": {"DClose": "DClose"}, 
                    "script": "(params.DClose < 0) ? -params.DClose : 0"
                }
            },

计算第上项收益和损失的 14 天周期简单移动平均和27 天周期指数移动平均

使用四个“moving_fn”聚合,命名为GainSMA, LossSMA, GainEWMA和 LossEWMA,GainSMA和LossSMA的参数窗口(window)为 14,而GainEWMA和 LossEWMA的参数窗口(window)为 100,并且α 值等于 0.071428571。参数“buckets_path”分别为各自的增益和损失。 参数“shift”设置为 1 以包含当天。 SMA 是使用未加权平均函数 (MovingFunctions.unweightedAvg) 计算,而EWMA 是使用指数移动平均函数 (MovingFunctions.ewma) 计算的。

            "GainSMA": {
                "moving_fn": {
                    "script": "MovingFunctions.unweightedAvg(values)", 
                    "window": 14, "buckets_path": "Gain", "shift":1
                }
            },
            "LossSMA": {
                "moving_fn": {
                    "script": "MovingFunctions.unweightedAvg(values)", 
                    "window": 14, "buckets_path": "Loss", "shift":1
                }
            },
            "GainEWMA": {
                "moving_fn": {
                    "script": "MovingFunctions.ewma(values, 0.071428571)", 
                    "window": 100, "buckets_path": "Gain", "shift":1
                }
            },
            "LossEWMA": {
                "moving_fn": {
                    "script": "MovingFunctions.ewma(values, , 0.071428571)", 
                    "window": 100, "buckets_path": "Loss", "shift":1
                }
            },

计算不同类型的相对强弱指数指标

本文讨论了Wilder 相对强弱指数(RSI)、使用14 天周期简单移动平均的相对强弱指数(SMARSI)、随机相对强弱指数(SRSI) 和随机相对强弱指数的7 天周期简单移动平均(MSRSI)。 为了获得SRSI,计算了 14 天期间的最大的 SRSI (HRSI) 和最小的 SRSI (LRSI)。 使用名为 RSI 的“bucket_script”聚合和参数“buckets_path”来指定来自 GainEWMA 和 LossEWMA 的结果。 然后根据相对强弱指数方程指定脚本。 同理,可以使用GainSMA 和LossSMA 得到SMARSI。 HRSI 和LRSI 分别使用MovingFunctions.max() 和MovingFunctions.min() 来找到14 天周期的最大值和最小值。 然后根据随机相对强弱指数程用脚本计算 SRSI。 最后,使用MovingFunctions.unweightedAvg计算SRSI的7天简单移动平均线,得到MSRSI。

                "RSI": {
                    "bucket_script": {
                        "buckets_path": {"GainEWMA": "GainEWMA", "LossEWMA": "LossEWMA"}, 
                        "script": "100 - 100/(1+params.GainEWMA/params.LossEWMA)"
                    }
                },                 
                "SMARSI": {
                    "bucket_script": {
                        "buckets_path": {"GainSMA": "GainSMA", "LossSMA": "LossSMA"}, 
                        "script": "100 - 100/(1+params.GainSMA/params.LossSMA)"
                    }
                }, 
                "HRSI": {
                    "moving_fn": {
		                "script": "MovingFunctions.max(values)", "window": 14,
		                "buckets_path": "RSI", "shift":1
	                }
                },
                "LRSI": {
	                "moving_fn": {
		                "script": "MovingFunctions.min(values)", "window": 14,
		                "buckets_path": "RSI", "shift":1
                    }
                },
                "SRSI": {
                    "bucket_script": {
                        "buckets_path": {"RSI": "RSI", "HRSI": "HRSI", "LRSI": "LRSI"}, 
                        "script": "(params.RSI – params.LRSI) /(params.HRSI - params.LRSI)"
                    }
                }, 
                "MSRSI": {
	                "moving_fn": {
		                "script": "MovingFunctions.unweightedAvg(values)", "window": 7,
		                "buckets_path": "SRSI", "shift":1
	                }
                },

过滤掉额外的文件

使用名为 SStartDate 的“bucket_selector”聚合和参数“buckets_path”指定“DateStr”来选择正确的存储桶。 选择标准是日期在 2021-05-01 GMT 或之后的那些桶(纪元时间为 1619827200000,以毫秒为单位)。

            "SStartDate": {
                "bucket_selector": {
                    "buckets_path": {"DateStr": "DateStr"}, 
                    "script": "params.DateStr >= 1619827200000L"
                }
            }

????????实验的结果会不同类型的相对强弱指数值。 由于实验涉及 24 只 ETF,我们编写了一个 Python 程序 index_srsi.py 来执行所有索引工作,包括从 fidelity24_fund 指数中读取每日价值,计算每种类型的对强弱指数并将其值索引到给定的索引名称。因此,回测程序只处理检索出的信号(值小于或大于交叉值)而不是所有值。 REST API 请求正文的以下代码是检索所有具有交叉值 70 和 30 的相对强弱指数信号。

{
    "query":{
        "bool": {
            "must": [{"range": {"date": {"gte": "2021-05-01", "lte": "2021-0930"}}}],
            "should":[{"range": {"RSI": {"gte": 70}}},{"range": {"RSI": {"lte": 30}}}],
            "minimum_should_match":1
        }
    },
    "sort": {"date":"asc", "symbol":"asc"},
    "size": 10000
}

????????为了确保只买入并持有一股,在卖出持有的股票之前没有发生任何交易,在 Python 字典中添加一个字段“share”来确保交易满足以下条件。

  • 如果 entry["share"] == 0,则兑现买入信号
  • 如果 entry["share"] > 0,则兑现卖出信号

????????从 Elasticsearch 检索信号,并处理响应以执行交易的 process_data() 函数如下所示:

# parse the response data and process the buy/sell signal
def process_data(resp, entries, rsi_type, hwm, lwm, balance_sheet):
    result = json.loads(resp)
    if "status" in result:
        print("Return status: %s, error: %s" % (result['status'], result['error']))
        sys.exit(-1)

    if result['hits']['total']['value'] > 0:
        hits = result['hits']['hits']
        for hit in hits:
            entry = entries[hit['_source']['symbol']]
            if hit['_source'][rsi_type] > hwm:
                if entry['share'] > 0:
                    entry['date'] = hit['_source']['date']
                    entry[rsi_type] = hit['_source'][rsi_type]
                    entry['close'] = hit['_source']['close']
                    trade = (entry['close'] - entry['buy']) * entry['share']
                    if trade > 0:
                        entry['num_of_win'] += 1
                    else:
                        entry['num_of_loss'] += 1
                    entry['profit'] += trade
            elif hit['_source'][rsi_type] < lwm:
                if entry['share'] == 0:
                    entry['date'] = hit['_source']['date']
                    entry['rsi'] = hit['_source']['rsi']
                    entry['buy'] = hit['_source']['close']
                    entry['share'] = 1
                    entry['num_of_trade'] += 1

????????Python 程序backtest_srsi.py将记录每个信号,无论该信号是否被兑现。 此外,还提供基准信息(开始日买入,最后交易日卖出)以与 相对强弱指数交易策略进行比较。 下面列出几条消息供参考。

$ ./backtest_srsi.sh -i indicators -s 2021-05-01 -e 2021-09-30 -t srsi -u 0.8 -l 0.2
input_index: 'indicators', start_date: '2021-05-01', end_date: '2021-09-30', type: 'srsi', high mark: '0.80', low mark '0.20'
Balance sheet : 
--------------------------------------------------------------------------------
['date:2021-05-03, symbol: FBCG, rsi: 0.000, close: 30.740 buy a share, num_of_trades: 1 ',
 'date:2021-05-03, symbol: FENY, srsi: 0.938, close: 13.700 no share, not sell',
……
'date: 2021-05-07, symbol: FCPI, buy: 28.640, close: 29.220, rsi: 1.000, share: 1, profit: 0.580, win: 1, loss: 0, total profit: 0.580',
……
'date: 2021-09-10, symbol: ONEQ, buy: 58.820, close: 56.180, share: 1, trade: -2.64 profit: -2.60',
 'symbol: ONEQ, num_of_trade: 4, win: 2, loss: 2, total profit: -2.600, benchmark_profit: 0.041']
--------------------------------------------------------------------------------

????????以下几个表收集了各种相对强弱指数交易策略的统计数据,包括 Wilder's RSI (70,30)、StochRSI、Smoothed StochRSI 、SMA RSI和 Wilder's RSI (65,35) 。数据由24 只随机挑选的 ETF从 2021-05-01 到 2021-09-30组成 。该表包括获胜次数、失败次数和总利润(忽略成本),基准利润也包括在内。 第一个表格显示了 StochRSI 和 Wilder RSI 的表现。 从观察的角度来看,StochRSI 远优于 RSI。 这是因为如果使用 RSI,24 只 ETF 中只有 7 只收到交易信号。 但是,与其他类型的 RSI 相比,StochRSI 的交易信号太多,也没有使结果变得更好。

????????第二个表格显示了平滑后的StochRSI和SMARSI的表现。尽管平滑后的StochRSI交易信号的数量显着减少,但表现更差。 最可能的原因是由于错过了上升和下降的精确峰值。 SMARSI的性能非常接近StochRSI,但交易次数要少得多。 ?

????????第三个表显示了具有交叉值 (35,65) 的 Wilder RSI和基准的性能。 在这个实验中,我得到了与前一篇文章相同的结论,即 RSI(35,65)表现最好。它的收益是基准的3倍。赢输的比例为16比14。大部分亏损是由于在实验最后一天强行抛售造成的。如果要下结论,在使用相对强弱指数时,需要有更长的缓冲时间来等待合适的时机卖出。 否则,当您因某种原因被迫卖出时,价格很可能会远低于您买入的价格。?

?

????????最后一个表格显示了本实验结果汇总。作为大多数交易者的建议,不要使用单一指标进行交易,因为可能会在错误的信号下进行交易。 根据编程代码,Elasticsearch 和 Python 可以无缝集成到技术分析中。


备注:

  1. 感谢Investors Exchange(IEX)开放社区提供相关数据及Gitee开源社区提供存储开源项目。
  2. 本文基于公开发布技术和研究观点,并不构成任何投资建议,读者在使用时须自行承担责任。
  3. 文中可能还存在疏漏和错误之处,恳请广大读者批评和指正。
  4. 作者的中文著作Elasticsearch 数据分析与实战应用(ISBN 978-7-113-27886-1号)将于2021 年 7 月出版。
  5. 作者的英文著作Advanced Elasticsearch 7.0(ISBN 978-1-789-95775-4号)被bookauthority评为 2021 年最值得阅读的 4 本 Elasticsearch 新书之一。
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-10-27 12:54:03  更:2021-10-27 12:54:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:56:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码