サンプルバックテストスクリプト[Python]

こんにちわ、ニッケルメッキです。
簡単で理解しやすそうなバックテストのサンプルスクリプトを書きましたので、置かせて頂きます。内容が把握しやすいように損益グラフの表示のみになります。
バックテストに必要なデータは下記のスクリプトを参考に入手のうえ動かして頂ければと思います。

import csv
import numpy as np
from collections import deque
import matplotlib.pyplot as plt
from datetime import datetime


# --- 各種パラメータ ------------------------------------------------------------
# バックテストで使用するファイル(CSV)
file_name = 'ohlc2019-06.csv'

# トレードパラメータ(移動平均)
first_ma_length = 25  # 短期
slow_ma_length = 50  # 長期
trade_size = 1  # 取引数量

# --- 変数・配列の初期化 ---------------------------------------------------------
# 指標用のバッファ
close = deque(maxlen=slow_ma_length)  # 指標計算に必要な期間分、終値を格納
first_ma = deque(maxlen=2)  # 前回と前々回分の移動平均を格納
slow_ma = deque(maxlen=2)

# バックテスト用
data = []  # OHLCVデータ
positions = []  # ポジション
profit_and_loss = []  # 損益
profit_and_loss.append(0)

# CSV読み込み
csv_file = open('ohlc_files/' + file_name, 'r')
reader = csv.reader(csv_file)
data = [r for r in reader]
csv_file.close()

# --- ポジション計算関数 ---------------------------------------------------------
def calculate_position_details(positions):
   position_size = 0  # サイズ
   average_price = 0.0  # 平均価格
   for p in positions:
       position_size += p['size']
       average_price += p['price'] * abs(p['size'])
   if position_size != 0:
       average_price = average_price / abs(position_size)
   return round(average_price), round(position_size, 8)

# --- バックテスト --------------------------------------------------------------
for d in (reversed(data)):

   # データがない期間はスキップ
   if d[5] == 'None':  # https://note.mu/milkchocofx/n/n3cf1166afffaのスクリプト使用時、通常のOHCLVの場合はd[4]
       continue

   # 始値・終値
   open = int(d[2])
   ltp = int(d[5])

   # ポジション取得
   position_size = 0.0
   average_price = 0
   average_price, position_size = calculate_position_details(positions)

   # 売買判定、損益計算
   if len(slow_ma) == 2:  # 指標が必要な期間揃い次第、取引開始
       # 前回の足がゴールデンクロスで買いデッドクロスで売り、売買価格は始値
       if first_ma[0] > slow_ma[0] and first_ma[1] < slow_ma[1]:
           # ポジションが存在する場合は損益計算、ポジションをクローズ(初期化)
           if position_size < 0:
               profit_and_loss.append((open -average_price) * abs(position_size) + profit_and_loss[-1])
               positions = []
           positions.append({'price': open, 'size': trade_size})  # ポジションの追加

       elif first_ma[0] < slow_ma[0] and first_ma[1] > slow_ma[1]:
           if position_size > 0:
               profit_and_loss.append((average_price - open) * position_size + profit_and_loss[-1])
               positions = []
           positions.append({'price': open, 'size': -trade_size})

   # 指標の計算(移動平均)
   close.append(ltp)
   close_list = list(close)
   # 指標計算に必要な期間が経過後に指標を計算
   if len(close_list) == slow_ma_length:
       first_ma.append(round(np.mean(close_list[-first_ma_length-1:-1])))
       slow_ma.append(round(np.mean(close_list[-slow_ma_length-1:-1])))

# --- 損益をプロット ------------------------------------------------------------
plt.plot(profit_and_loss)
plt.show()

この記事が気に入ったら、サポートをしてみませんか?気軽にクリエイターを支援できます。

30

ニッケルメッキ

相場好きです!それだけ。

仮想通貨

1つ のマガジンに含まれています
コメントを投稿するには、 ログイン または 会員登録 をする必要があります。