詳細 ⋅ 2020年8月18日午後10時30分 tradingviewのストラテジーバックテスターは素晴らしく、少ないコードで簡単にバックテストプログラムを 書くことが出来て、あらゆるデータを提供してくれます。 ただ、システムを作成してあらゆるパラメータ値を試して損益の統計量を取り、そのシステムの堅牢性 や優位性を測定する機能はありません。 これはMT4やトレードステーションにはウォークフォワードオプティマイザーがあるようですが、 tradingviewには無いのでPythonのseleniumを使って実装しました。 seleniumのchrome.driverを使うとwebブラウザを自動操作できるのでdriverでチャート画面を開き、 設定画面から仕掛けのパラメータ値の最小値から最大値まで自動入力し、損益や勝率、平均利益などの数値をcssセレクタで スクレイピングして取得していきます。 取得したデータはpandasやnumpyで整形し、平均値や標準偏差などのデータを表示しました。 試しにインサイドデイストラテジーを作成し、インサイドデイの発生したバーの数を1~3、終値が1~3 本前の高値より高ければロング、低ければショートのロジックでバックテストをした結果、全体で利益がでたのは 全てのパラメータセットで22%しかありませんでした。 一見良さそうなパラメータで最適化しても、少しパラメータが変わっただけで使い物にならなくなるという ガラクタのシステムだったということがよくわかります。 良いシステムとはパラメータが変わっても利益を出せる堅牢性が備わっているシステムですね。 戦略名= インサイド・デイ ↓ 行= インサイド・デイ = 1 ~ 3 → 列= バーバック = 1 ~ 3 1 2 3 1 158420 130880 -87310 2 -4820 -39700 -12580 3 -22030 -26490 -14650 利益率= 22 % 平均勝率= 38 % 平均AVGトレード= -960 平均値= 9080 中央値= -14650 標準偏差= 76206 -------------------- 最高値= 158420 インサイド・デイ = 1 バーバック = 1 import numpy as np import pandas as pd from mpl_toolkits.mplot3d import axes3d import matplotlib as mpl import matplotlib.pyplot as plt from matplotlib import cm import csv import matplotlib as mpl import matplotlib.pyplot as plt stType = int(input('パラメータ数を入力 :')) if stType == 1: with open(CSVファイル\パラメータ1.csv",encoding='utf8') as f: reader = csv.reader(f) l = [row for row in reader] p = l.pop(0) #平均勝率と平均AVGトレードを求める式 l_len = len(l) jlist = [] klist = [] for j in range(l_len): wins = int(l[j].pop(2)) avgW = int(l[j].pop(2)) jlist.append(wins) klist.append(avgW) j_avg = round(sum(jlist)/l_len) k_avg = round(sum(klist)/l_len) param = p[1] stname = p[0] print("\n","戦略名=",stname) A = np.array(l, dtype=np.int) B = A.transpose() y = B[0] x = B[1] df =pd.DataFrame(x,index=y,columns=[param]) print("\n",df) ave = np.mean(df) mid = np.median(df) std = np.std(df) count = (df.count()).sum() success = (x>0).sum() result = int(success/count*100) print("") print('利益率=',result,'%') print('平均勝率=',j_avg,'%') print('平均AVGトレード=',k_avg) print('平均値=',int(ave)) print('中央値=',int(mid)) print('標準偏差=',int(std)) print("--------------------") maxlist = [] A = (df.max()) idM = int(df.idxmax()) B = (int(A)) maxlist.append(B) maxlist.append(idM) print("最高値=",int(A)) print(param,"=",int(maxlist[1])) plt.figure(figsize=(12,6)) plt.rcParams["figure.subplot.bottom"] = 0.2 plt.style.use('seaborn') plt.plot(y,x,'-') plt.plot(y,x,'ro') plt.xlabel(param,fontname="MS Gothic") plt.ylabel('損益',fontname="MS Gothic") plt.title(stname,fontname="MS Gothic") plt.show() CV = open(CSVファイル\ウォークフォワード1.csv','a',newline='',encoding='utf8') csvWriter = csv.writer(CV) csvWriter.writerow(maxlist) CV.close() elif stType == 2: with open(CSVファイル\パラメータ2.csv",encoding='utf8') as f: reader = csv.reader(f) l = [row for row in reader] p2 = l.pop(0) #平均勝率と平均AVGトレードを求める式 l_len = len(l) jlist = [] klist = [] for j in range(l_len): wins = int(l[j].pop(3)) avgW = int(l[j].pop(3)) jlist.append(wins) klist.append(avgW) j_avg = round(sum(jlist)/l_len) k_avg = round(sum(klist)/l_len) stname = p2[0] param1 = p2[1] param2 = p2[2] print("\n","戦略名=",stname) A = np.array(l, dtype=np.int) B = A.transpose() y = B[0] x = B[1] z = B[2] Ymax = y.max() Ymin = y.min() Ylen1 = np.unique(y) Ydata = len(Ylen1) Xmax = x.max() Xmin = x.min() Xlen1 = np.unique(x) Xdata = len(Xlen1) print("") print("↓ 行=",param1,'=',Ymin,'~',Ymax) print("→ 列=",param2,'=',Xmin,'~',Xmax) xx = np.linspace(Xmin,Xmax,Xdata) yy = np.linspace(Ymin,Ymax,Ydata) z2 = z.reshape(Ydata,Xdata) df =pd.DataFrame(z2,index=Ylen1,columns=Xlen1) print(df) count = (df.count()).sum() success = (z>0).sum() result = int(success/count*100) print("") print('利益率=',result,'%') print('平均勝率=',j_avg,'%') print('平均AVGトレード=',k_avg) ave = np.mean(z) mid = np.median(z) std = np.std(z) print('平均値=',int(ave)) print('中央値=',int(mid)) print('標準偏差=',int(std)) print("--------------------") maxlist2 = [] A = (df.max()) B = (A.max()) C = (A.idxmax()) idm = (df[C].idxmax()) maxlist2.append(B) maxlist2.append(idm) maxlist2.append(C) print("最高値=",B) print(param1,"=",idm) print(param2,"=",C) xx,yy = np.meshgrid(xx,yy) zs = np.array(z) zz = zs.reshape((Ydata,Xdata)) zero = np.linspace(0,0,num=count) zero_z = zero.reshape((Ydata,Xdata)) fig = plt.figure(figsize=(12,6)) ax = fig.gca(projection='3d') ax.plot_wireframe(xx,yy,zero_z, color = "w", alpha = 0.0) surf = ax.plot_surface(xx,yy,zz,cstride=1,rstride=1,cmap='coolwarm',edgecolor="k",alpha=0.9) ax.set_ylabel(param1,fontname="MS Gothic") ax.set_xlabel(param2,fontname="MS Gothic") ax.set_zlabel('損益',fontname="MS Gothic") ax.set_title(stname,fontname="MS Gothic") fig.colorbar(surf, shrink=1, aspect=6) plt.show() CV = open(CSVファイル\ウォークフォワード2.csv','a',newline='',encoding='utf8') csvWriter = csv.writer(CV) csvWriter.writerow(maxlist2) CV.close() else: print('パラメータ数が正しくありません')