iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0
AI/ ML & Data

從投信數據預測葛蘭碧突破後股價走勢系列 第 7

[Day 07] 找出最適合的均線(2)

  • 分享至 

  • xImage
  •  

前言

上一篇我們用了加權的方式,幫股票的未來漲幅算了一個加權分數,還做了一個從10MA到200MA的Boxplot列表。從結果來看,每個MA下的中位數其實差不多,沒有特別顯著的差異。這次,我們要改進一下加權分數的算法,看看能不能讓我們更好地選出長、中、短期MA,讓分析結果更明顯一些。

調整加權分數之參數

因為上一篇的參數是我自己隨意設定的,結果可能不太理想,所以這次我決定調整一下加權計算的參數。我們會使用 Grid SearchCV(網格搜索) 來幫我們找出更好的參數組合。簡單來說,Grid SearchCV 是一種方法,它會自動幫我們試出所有可能的超參數組合,找出最佳的模型配置,讓結果更精確。

下面是使用 Grid SearchCV 進行計算的程式碼:

匯入必要的套件

import pandas as pd
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LinearRegression
import numpy as np

讀取所有 CSV 檔案

import os

folder_path = r'C:\iThome\raaa'
all_files = [f for f in os.listdir(folder_path) if f.endswith('.csv')]

data_frames = []
for file in all_files:
    df = pd.read_csv(os.path.join(folder_path, file))
    data_frames.append(df)

# 合併所有資料
data = pd.concat(data_frames, ignore_index=True)

設定目標變數與特徵

X = data[['5日漲跌幅', '20日漲跌幅', '60日漲跌幅', '5日最大漲幅', '20日最大漲幅', '60日最大漲幅']]
y = data['future_return']

設置權重參數範圍

param_grid = {
    '5日漲跌幅_weight': [0.1, 0.2, 0.3],
    '20日漲跌幅_weight': [0.1, 0.2, 0.3],
    '60日漲跌幅_weight': [0.05, 0.1, 0.2],
    '5日最大漲幅_weight': [0.1, 0.2, 0.3],
    '20日最大漲幅_weight': [0.1, 0.15, 0.2],
    '60日最大漲幅_weight': [0.05, 0.1, 0.2],
}

自定義加權模型

class WeightedModel:
    def __init__(self, **weights):
        self.weights = weights

    def fit(self, X, y=None):
        return self

    def predict(self, X):
        weighted_sum = (
            X['5日漲跌幅'] * self.weights['5日漲跌幅_weight'] +
            X['20日漲跌幅'] * self.weights['20日漲跌幅_weight'] +
            X['60日漲跌幅'] * self.weights['60日漲跌幅_weight'] +
            X['5日最大漲幅'] * self.weights['5日最大漲幅_weight'] +
            X['20日最大漲幅'] * self.weights['20日最大漲幅_weight'] +
            X['60日最大漲幅'] * self.weights['60日最大漲幅_weight']
        )
        return weighted_sum

    # 添加 get_params 讓 GridSearchCV 可以提取參數
    def get_params(self, deep=True):
        return self.weights

    # 添加 set_params 讓 GridSearchCV 可以設置參數
    def set_params(self, **params):
        for key, value in params.items():
            self.weights[key] = value
        return self

使用 GridSearchCV 進行超參數調整

from sklearn.model_selection import GridSearchCV

model = WeightedModel()
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, scoring='neg_mean_squared_error', cv=5)

grid_search.fit(X, y)

輸出最優權重參數

print(f"Best weights: {grid_search.best_params_}")
print(f"Best score: {grid_search.best_score_}")

程式輸出為:

Best weights: {'20日最大漲幅_weight': 0.2, '20日漲跌幅_weight': 0.3, '5日最大漲幅_weight': 0.1, '5日漲跌幅_weight': 0.3, '60日最大漲幅_weight': 0.05, '60日漲跌幅_weight': 0.05}

各均線的平均加權分數

接下來,我們可以列出每個 MA_window 的平均加權分數,這樣可以幫助我們判斷哪條均線表現得比較好。

以下是各均線的平均加權分數:
平均加權分數

不過,因為加權分數中有一些離群值出現,我們這次使用了四分位距(IQR)來計算離群值的範圍,並把超出這個範圍的值給移除。這是移除離群值後的結果:
移除離群值後的結果

移動平均線的分類與期間選擇

根據 Investopedia 提到的「最常使用的移動平均線 (MA) 期間」

  • 長期投資者:常用 100 天、200 天與 500 天的移動平均線
  • 短期交易者:常用 5 天、10 天、20 天與 50 天的移動平均線

我們可以進一步將這些期間分成三類:

  • 短期MA:10MA ~ 50MA
  • 中期MA:50MA ~ 100MA
  • 長期MA:100MA ~ 500MA

根據我們先前計算的平均加權分數,我們可以採用以下期間作為基準:

  • 短期MA:30MA
  • 中期MA:100MA
  • 長期MA:200MA

這樣就找出長中短均線了。

結論

這篇文章中,我們通過改進加權分數的算法,成功選出了適合的長、中、短期移動平均線。透過使用 Grid SearchCV,我們找到了更佳的權重參數,這不僅提升了模型的精確度,還讓我們更清楚地理解各均線的表現。

在平均加權分數的分析中,雖然最初的數據中出現了一些離群值,但透過四分位距(IQR)進行處理後,我們得到了更乾淨的數據,讓分析結果更具參考價值。最終,我們根據 Investopedia 提到的常用期間,將移動平均線分類為短期(30MA)、中期(100MA)及長期(200MA),這樣的分類也能幫助我們在投資決策時更加明確。


上一篇
[Day 06]找出最適合的均線(1)
下一篇
[Day 08] RNN/LSTM? (1)
系列文
從投信數據預測葛蘭碧突破後股價走勢17
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言