[BTC][Bot] [Python] 第四回 取引所の取引データを使ってローソク足を作る

はじめに

こんにちは _santa365です。
第一回 はじめのBot環境構築 ではベースとなるプロジェクトの作成、
第二回 取引所の取引データを取得する では実際の取引所と通信をしてデータの取得、
第三回 取引所の取引データを保存する では取引所の通信で取得した情報をファイルに保存する、を行いました。

今回は第三回の内容をもとに実際の取引データを使ってローソク足を作って行きたいと思います。

ローソク足を作る前に

ローソク足を作る前に目的を明確にしておきます。というのも目的によってローソク足の出力形式を調整する必要があるからです。今回の記事で作るローソク足は、今後のバックテストのために使います。

バックテストには、kernc/backtesting.py を使う予定です。なのでbacktesting.pyで使える形式の出力をします。kernc/backtesting.py で使ってるCSVは下記のような形式になっています(参考: GOOG.csv)。

,Open,High,Low,Close,Volume
2017-04-19 09:00:00,1.0716,1.0722,1.07083,1.07219,1413
2017-04-19 10:00:00,1.07214,1.07296,1.07214,1.0726,1241
2017-04-19 11:00:00,1.07256,1.07299,1.0717,1.07192,1025
2017-04-19 12:00:00,1.07195,1.0728,1.07195,1.07202,1460

なので第三回 取引所の取引データを保存するで保存したデータを上記のような形式に変換するというのが本記事の主題です。

ローソク足を作る

ローソク足を作っていきましょう。ローソク足の生成のロジックはpandasを使います。pandasはpythonにおけるデータ分析でほぼ必須のライブラリです。非常に有用なのでぜひ活用していきましょう。
例のごとく、インストールからしていきます

$ poetry add pandas

ではコードを書いていきましょう。スクリプトファイル`script/ohlc.py`を新規に作成します。
今回の場合、スクリプトを実行するときにファイル名を指定できたほうが利便性は高いです。なのでスクリプトを実行する際にファイル名を指定できるようにします。またローソク足の期間も同じように指定できるようにします。

poetry run python script/ohlc.py -f data/ftx/raw/2021-08-12.csv -p 1min 15min 1h

上記のケースのようにスクリプト実行時に値を渡す方法はいくつかあるのですが、今回は標準ライブラリのargparseを使うことにします。理由としては標準ライブラリなのでインストール不要なのと今回のケースは複雑ではないのでargparseで十分だからです。

メインのロジックを書く前にスクリプト実行時に渡された値の処理を書きます。

#!/usr/bin/env python
import argparse
import os
from typing import TextIO


def main() -> None:
   args = parse_args()
   pass


def is_valid_file(parser, arg) -> TextIO:
   if not os.path.exists(arg):
       parser.error("The file %s does not exist!" % arg)
   else:
       return open(arg, 'r')  # return an open file handle


def parse_args() -> argparse.Namespace:
   parser = argparse.ArgumentParser(description='ohlc generator')
   parser.add_argument("-f", "--file", required=True, help="input file", metavar="FILE",
                       type=lambda x: is_valid_file(parser, x))
   parser.add_argument("-p", '--period', required=True, help="input period", metavar="PERIOD",
                       nargs='+')
   return parser.parse_args()


if __name__ == '__main__':

   main()

一度こちらを実行してみましょう。下記のように使い方が出ればうまく行ってます。

$ poetry run python script/ohlc.py -h
usage: ohlc.py [-h] -f FILE -p PERIOD [PERIOD ...]
ohlc generator
optional arguments:
 -h, --help            show this help message and exit
 -f FILE, --file FILE  input file
 -p PERIOD [PERIOD ...], --period PERIOD [PERIOD ...]
                       input period

次に実際のメインのロジックを書いていきます。
メインのロジックは以下のようになります。

import pandas as pd

def main() -> None:
   args = parse_args()

   data_frame = pd.read_csv(args.file, header=0, index_col='time', parse_dates=['time'])
   for period in args.period:
       resampled = data_frame['price'].resample(period).ohlc()

       filepath = args.file.name.replace('raw', period)
       if not os.path.isdir(os.path.dirname(filepath)):
           os.makedirs(os.path.dirname(filepath), exist_ok=True)

       resampled.to_csv(filepath, encoding='utf-8', index=True)

簡単にですが解説します。
はじめにPandasのread_csv関数を呼び出して、Dataframeオブジェクトを作ります。Dataframeオブジェクトは二次配列のデータオブジェクトで様々データに変換できたり出力できたりします。また通常の二次配列より計算速度が早くなっています。

次に作成したデータオブジェクトのpriceに対してリサンプリングを行います。ohlcはローソク足のことです(open high low closeの略)。periodはコマンドラインで入力した値が入っています。たったこれだけで期間ごとのローソク足のdataframeオブジェクトを新たに生成できます。便利ですね。

最後にそれをCSVで出力すれば完了です。最終的なコードは以下のようになります。

#!/usr/bin/env python
import argparse
import os
import pandas as pd


def main() -> None:
   args = parse_args()

   data_frame = pd.read_csv(args.file, header=0, index_col='time', parse_dates=['time'])
   for period in args.period:
       resampled = data_frame['price'].resample(period).ohlc()

       filepath = args.file.name.replace('raw', period)
       if not os.path.isdir(os.path.dirname(filepath)):
           os.makedirs(os.path.dirname(filepath), exist_ok=True)

       resampled.to_csv(filepath, encoding='utf-8', index=True)


def is_valid_file(parser, arg) -> str:
   if not os.path.exists(arg):
       parser.error("The file %s does not exist!" % arg)
   else:
       return arg


def parse_args() -> argparse.Namespace:
   parser = argparse.ArgumentParser(description='ohlc generator')
   parser.add_argument("-f", "--file", required=True, help="input file", metavar="FILE",
                       type=argparse.FileType('r', encoding='UTF-8'))
   parser.add_argument("-p", '--period', required=True, help="input period", metavar="PERIOD",
                       nargs='+')
   return parser.parse_args()


if __name__ == '__main__':
   main()

以上でローソク足の作成は完了です。おつかれさまでした!
次は実際に作成したデータを使ってバックテストを実施していきたいと思います。

Twitterで最新記事情報等流しています!お見逃しがないようフォローまたはリストに追加していただけると幸いです!

この記事が気に入ったらサポートをしてみませんか?