1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日経平均株価の予想

Last updated at Posted at 2022-01-10

日経平均株価を予想するためにすること

 まず始めに日経平均株価をPythonで予想して、投資に役立てたいという熱意がありました。
 そのためにPPDACサイクル(Problem->Plan->Data->Analysis->Conclusion)を回すことを考えてみました。

今回のPPDACサイクル

 Problem:日経平均株価の動きを予想したい!
 Plan:日経平均株価、出来高、空売り比率から予想する(ことができるのでは?という仮定)
 Data:日経平均株価と出来高は、pandas-datareaderから取得する。空売り比率は、下記サイトからPDFファイルを集め、Pythonでcsv出力する。
JPXサイト
https://www.jpx.co.jp/markets/statistics-equities/short-selling/index.html
 Analysis:それぞれの相関関係を調べる。(前編では扱わないです。というか後編があるかも分からないです。)
 Conclusion:未定。。。相関関係があれば良いのだけど。

Data取得

(1)pandas-datareaderを用いた日経平均株価と出来高の取得+csv出力

株価取得のソースコード
 終値の値のみをcsv出力しています。

import pandas_datareader.data as web
import datetime
import csv

year = '22'
month = '01'

start = datetime.datetime(2022, 1, 1)
end = datetime.datetime(2022, 1, 31)
tsd = web.DataReader("^N225", "yahoo", start, end)
print(tsd)

with open(f'./20220110_NIKKEI/csv/{year}{month}Close_price.csv', 'w') as f:
    writer = csv.writer(f)
    writer.writerow(tsd['Close'])

出来高取得のソースコード
 出来高をcsv出力しています。

import pandas_datareader.data as web
import datetime
import csv

year = '22'
month = '01'

start = datetime.datetime(2022, 1, 1)
end = datetime.datetime(2022, 1, 31)
tsd = web.DataReader("^N225", "yahoo", start, end)
print(tsd)

with open(f'./20220110_NIKKEI/csv/{year}{month}Volume.csv', 'w') as f:
    writer = csv.writer(f)
    writer.writerow(tsd['Volume'])

(2)JPXサイトから取得したpdfファイルをcsv出力

 まずはJPXサイトからpdfファイルをダウンロードします。
これにはchromeの拡張機能の"DownThemAll!"を使用しました。(ファイルを1回しかダウンロードしないため、あまりソースコード化する必要を感じませんでした。。。)
https://chrome.google.com/webstore/detail/downthemall/nljkibfhlpcnanjgbnlnbjecgicbjkge?hl=en

 ダウンロードしたPDFファイルのテキスト化
ダウンロードしたPDFファイルをテキストファイル化しています。

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import os

input = './20220110_NIKKEI/pdf/'

def pdf2text(yearMonth, yearMonthDay):
    input_path = f'./20220110_NIKKEI/pdf/{yearMonth}/{yearMonthDay}-m.pdf'
    output_path = f'./20220110_NIKKEI/pdf/{yearMonth}/{yearMonthDay}-m.txt'

    manager = PDFResourceManager()

    with open(output_path, "wb") as output:
        with open(input_path, 'rb') as input:
            with TextConverter(manager, output, codec='utf-8', laparams=LAParams()) as conv:
                interpreter = PDFPageInterpreter(manager, conv)
                for page in PDFPage.get_pages(input):
                    interpreter.process_page(page)

for i in range(32):
    if i < 10:
        ym = '202110'
        ymd = f'21100{i}'
        input_file = f'{input}{ym}/{ymd}-m.pdf'
        if(os.path.exists(input_file)):
            pdf2text(ym, ymd)
    else:
        ym = '202110'
        ymd = f'2110{i}'
        input_file = f'{input}{ym}/{ymd}-m.pdf'
        if(os.path.exists(input_file)):
            pdf2text(ym, ymd)
else:
    print('FINISH!')

次にテキスト化ファイルのcsv出力します。
色々、ハマる所はありましたが、csv出力する箇所は、「価格規制ありの空売り比率」に絞りました。

import os
import csv

year = '21'
month = '10'
pathOrigin = './20220110_NIKKEI/text/'
new_list = []
final_list = []

def short_ratio(nameNum):
    new_path = f'{pathOrigin}{year}{month}{nameNum}-m.txt'
    with open(new_path) as f:
        contents = f.readlines()[44]
        new_list.append(contents)
        #print(new_list)

for i in range(32):
    if i < 10:
        num = f'0{i}'
        path_Under = f'{pathOrigin}{year}{month}{num}-m.txt'
        if(os.path.exists(path_Under)):
            short_ratio(num)
    else:
        num = i
        path_Over = f'{pathOrigin}{year}{month}{num}-m.txt'
        if(os.path.exists(path_Over)):
            short_ratio(i)

#print(new_list)
for list in new_list:
    list = list.replace('%\n', '')
    final_list.append(list)

print(final_list)

path_final = f'./20220110_NIKKEI/csv/{year}{month}short.csv'
with open(path_final, 'w') as f:
    writer = csv.writer(f)
    writer.writerow(final_list)

本記事は、私の備忘録的な扱いです。。。

 結構、苦労してここまで来ました(祝日1日使いました)が、分析まで至らず残念でした。。。

後日談というか後編

単回帰分析による日経平均株価の予想プログラムを書いたよー

import pandas_datareader.data as pdr
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

start="2022/10/10"
end="2022/11/10"

n225=pdr.DataReader("NIKKEI225", "fred", start, end).dropna()
ln_n225=np.log(n225.dropna())
ln_n225.columns=['Close']
y=ln_n225
x=range(len(ln_n225))
x=sm.add_constant(x)
model=sm.OLS(y, x)
results=model.fit()

print(results.summary())

plt.plot(y, label='Close', color="blue")
results.fittedvalues.plot(label='prediction', style='--')
plt.ylabel('log(n225 index)')
plt.legend(loc='upper left')

plt.show()

future_Results=results.params[0]+results.params[1]*(len(x)+1)
print(f'明日の日経平均予想価格は、{int(np.exp(future_Results))}です。')

何をしているかと言うと?

日経平均株価の対数から単回帰直線を引き、その直線を伸ばして「明日の日経平均株価」を予測しています。
(精度は保証しません!)

GitHubで公開しているよー

追加記事

日経平均株価と商品先物価格との相関関係を調べたよ

日経平均株価とカカオ・銅・砂糖の先物価格の相関係数を調べました。
結果:相関係数0.63→0.68(コードを修正しました)
処理:日経平均価格終値 vs (カカオ * a)^pa * (銅 * b)^pb - (砂糖 * c)^pcという数式を立てて、機械学習っぽいことで最適化しました。
以下、Pythonコードです。

import yfinance as yf
import pandas as pd
from scipy.optimize import minimize
from scipy.stats import pearsonr

class Data:
    def __init__(self, symbol, start_date, end_date):
        self.symbol = symbol
        self.start_date = start_date
        self.end_date = end_date
    
    def get_data(self):
        data = yf.download(self.symbol, start=self.start_date, end=self.end_date)
        return data["Close"].to_frame(name=self.symbol)  # 終値のDataFrameを返す

# インスタンスの作成とデータの取得
cacao_instance = Data("CC=F", "1990-01-01", "2024-03-31")
cacao_close_df = cacao_instance.get_data().rename(columns={"CC=F": "Cacao Close"})

copper_instance = Data("HG=F", "1990-01-01", "2024-03-31")
copper_close_df = copper_instance.get_data().rename(columns={"HG=F": "Copper Close"})

sugar_instance = Data("SB=F", "1990-01-01", "2024-03-31")
sugar_close_df = sugar_instance.get_data().rename(columns={"SB=F": "Sugar Close"})

nikkei_instance = Data("^N225", "1990-01-01", "2024-03-31")
nikkei_close_df = nikkei_instance.get_data().rename(columns={"^N225": "Nikkei Close"})

exchange_instance = Data("JPY=X", "1990-01-01", "2024-03-31")
exchange_rate_df = exchange_instance.get_data().rename(columns={"JPY=X": "Exchange Rate"})

# データフレームの結合とドル建て日経平均株価の計算
merged_data = pd.concat([cacao_close_df, copper_close_df, sugar_close_df, nikkei_close_df, exchange_rate_df], axis=1)
merged_data["Nikkei Close USD"] = merged_data["Nikkei Close"] / merged_data["Exchange Rate"]
merged_data_clean = merged_data.dropna()

# 目的関数
def objective(params):
    a, p_a, b, p_b, c, p_c = params
    mixed_close = (merged_data_clean['Cacao Close'] * a) ** p_a * \
                  (merged_data_clean['Copper Close'] * b) ** p_b - \
                  (merged_data_clean['Sugar Close'] * c) ** p_c
    corr, _ = pearsonr(mixed_close, merged_data_clean['Nikkei Close USD'])
    return -corr

# 初期係数と冪乗、最適化の実行、結果の表示
initial_params = [1, 1, 1, 1, 1, 1]  # 係数と冪乗の初期値
result = minimize(objective, initial_params, method='BFGS')
print(f"Optimized Coefficients and Powers: {result.x}")
print(f"Maximum Correlation: {-result.fun}")
1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?