最新論文紹介 収益性の高いデイトレード戦略 「A Profitable Day Trading Strategy For The U.S. Equity Market」⑦

 ではプログラムで実装していきたいと思います。


まずは銘柄の時価情報を取得しないと始まりません。

無料かつ5分足のデータが取れるサービスはないかと探したところYahoo Finance APIというのがありました。

Pythonのライブラリもあり使いやすそうなのでこれを使います。

https://github.com/ranaroussi/yfinance


いざ実装!

使用するライブラリ

import csv
import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import time
import os
import json

対象銘柄一覧の取得

まずは東証の銘柄コード一覧を取得していきましょう。
これもプログラムで取得できれば良いのですが、とりあえずはファイルをダウンロードして配置する形にします。


def getStockSymbol():
  header=[]
  data=[]
  with open('./stock_symbol/data_j.csv','r', encoding='shift-jis') as f:
    reader=csv.reader(f)
    header=next(reader)
    for row in reader:
      data.append(row)
  return header, data
  
stock_symbol_header, stock_symbol_data = getStockSymbol()
symbol_idx=stock_symbol_header.index('コード')
symbol_list=[x[symbol_idx]+'.T' for x in stock_symbol_data]

番号に加えて末尾に'.T'が必要なようなのでその前処理もします。

対象期間と保存場所の作成

営業日で過去14日間分のデータがあればよいが、土日祝日を考慮した期間指定を考えるのはめんどい。
なので余裕を見て今日から40日前までのデータを取得するようにする。
一応取得したデータと計算結果をCSVとして保存するのでディレクトリを作る。

def getTragetDate():
  today = datetime.today().date()
  tomorrow = today + timedelta(days=1)
  before_date = today - timedelta(days=40)
  return tomorrow, before_date

def createFolder(path):
  # フォルダが存在しない場合に作成
  if not os.path.exists(path):
      os.makedirs(path)
      print(f'フォルダ {path} が作成されました')
  else:
      print(f'フォルダ {path} は既に存在します')

end_date, start_date = getTragetDate()
str_start_date=str(start_date)
str_end_date=str(end_date)
path=f'~filter_stock_for_5minetues_ORB_strategy\\stock_data\\{str_start_date}-{str_end_date}'
createFolder(path)

ATRと相対出来高を計算する関数の実装

yfinanceから取得できるデータはPandasのDataFrame。
def calculate_atr(data, period=14):
  """
  ATR (Average True Range) を計算します。

  Parameters:
  - data: DataFrame。最低限 'High', 'Low', 'Close' の列が必要です。
  - period: ATRの計算に使用する期間(デフォルトは14)。

  Returns:
  - ATRを含むSeriesを返します。
  """
  # 前日の終値
  data['previous_close'] = data['Close'].shift(1)

  # 真の値幅(True Range)の計算
  data['high_low'] = data['High'] - data['Low']
  data['high_prev_close'] = (data['High'] - data['previous_close']).abs()
  data['low_prev_close'] = (data['Low'] - data['previous_close']).abs()

  # 3つの中で最大のものがTrue Range
  data['TR'] = data[['high_low', 'high_prev_close', 'low_prev_close']].max(axis=1)

  # 最初の `period` 日間のデータが不足する場合に `NaN` が出ないようにするために `min_periods` を設定
  atr = data['TR'].rolling(window=period, min_periods=1).mean()

  return atr

def calculate_relative_volume(data, period=14):
    """
    相対出来高を計算します。

    Parameters:
    - data: DataFrame。最低限 'Volume' の列が必要です。インデックスが 'Datetime' の形式である必要があります。
    - period: 過去何日間の平均出来高を基にするか(デフォルトは14日)。

    Returns:
    - relative_volume_df: 相対出来高を含むDataFrame
    """
    # インデックスを datetime に変換(もしまだされていない場合)
    if not pd.api.types.is_datetime64_any_dtype(data.index):
        data.index = pd.to_datetime(data.index)

    # 日本時間9:00から9:05までのデータを抽出
    data_opening_5min = data.between_time('09:00', '09:04')

    # 明示的にコピーを作成してから操作
    data_opening_5min = data_opening_5min.copy()

    # 各日の5分間の取引量を合計
    data_opening_5min['date_only'] = data_opening_5min.index.date
    
    daily_first_5min_volume = data_opening_5min.groupby('date_only')['Volume'].sum()

    # 過去14日間の移動平均を計算
    rolling_avg_volume = daily_first_5min_volume.rolling(window=period).mean()

    # 相対出来高の計算: 当日の出来高 / 過去14日間の平均出来高
    relative_volume = daily_first_5min_volume / rolling_avg_volume

    # 結果をDataFrameにまとめる
    relative_volume_df = pd.DataFrame({
        'Date': daily_first_5min_volume.index,
        'First_5min_Volume': daily_first_5min_volume,
        'Rolling_Avg_Volume': rolling_avg_volume,
        'Relative_Volume': relative_volume
    })

    return relative_volume_df

続きはまた次回!

コメント