日経平均株価の予想

# 日経平均株価を予想するためにすること
　まず始めに日経平均株価を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出力しています。

```Python
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出力しています。

```Python
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ファイルをテキストファイル化しています。

```Python
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出力する箇所は、「価格規制ありの空売り比率」に絞りました。

```Python
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日使いました）が、分析まで至らず残念でした。。。

# 後日談というか後編
単回帰分析による日経平均株価の予想プログラムを書いたよー
```Python
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で公開しているよー
https://github.com/Kouhei-Takagi/NIKKEI-Price

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

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

```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}")
```