過去のCryptowatchの価格データで売買シグナルを検証をする

売買シグナルをpythonで実装し、実際にどのようなチャートでシグナルが点灯するのかを確認したい場合、リアルタイムの価格データで検証するのは時間の無駄です。

特にちょっとしたパラメーター(%など)の調整のために、どのようなローソク足がヒットするかを確認したいだけであれば、リアルタイムのデータを使う必要はありません。

今回の記事では、Cryptowatchで取得できるBitflyerの価格の過去データからシグナルを検証する方法を紹介します。

今回、検証する売買シグナル

前回までの記事で紹介した「(酒田五法の)赤三兵というチャートパターンを買いシグナルにするpythonコード」を使って説明していきます。そのため、こちらで紹介しているコードを改良するかたちで説明します。

・前回の記事

検証用のコード


import requests
from datetime import datetime
import time

response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc",params = { "periods" : 60 })

def get_price(min,i):
	data = response.json()
	last_data = data["result"][str(min)][i]

	return { "close_time" : last_data[0],
		"open_price" : last_data[1],
		"high_price" : last_data[2],
		"low_price" : last_data[3],
		"close_price":last_data[4] }


def print_price( data ):
	print( "時間: " + datetime.fromtimestamp(data["close_time"]).strftime('%Y/%m/%d %H:%M') + " 始値: " + str(data["open_price"]) + " 終値: " + str(data["close_price"]) )


def check_candle( data ):
	realbody_rate = abs(data["close_price"] - data["open_price"]) / (data["high_price"]-data["low_price"]) 
	increase_rate = data["close_price"] / data["open_price"] - 1

	if data["close_price"] < data["open_price"] : return False
	elif increase_rate < 0.0005 : return False
	elif realbody_rate < 0.5 : return False
	else : return True


def check_ascend( data,last_data ):
	if data["open_price"] > last_data["open_price"] and data["close_price"] > last_data["close_price"]:
		return True
	else:
		return False


last_data = get_price(60,0)
print_price( last_data )
time.sleep(10)

flag = 0
i = 1

while i < 500:	
	data = get_price(60,i)
	
	if data["close_time"] != last_data["close_time"]:
		print_price( data )
		
		if flag == 0 and check_candle( data ):
			flag = 1
		elif flag == 1 and check_candle( data )  and check_ascend( data,last_data ):
			print("2本連続で陽線")
			flag = 2
		elif flag == 2 and check_candle( data )  and check_ascend( data,last_data ):
			print("3本連続で陽線 なので 買い!")
			flag = 3
		else:
			flag = 0
		
		last_data["close_time"] = data["close_time"]
		last_data["open_price"] = data["open_price"]
		last_data["close_price"] = data["close_price"]
	
	i += 1
	time.sleep(0)

前回の実践用のコードからの主な変更点は3か所だけです。

上記のコードには無駄な部分もあり、もっとコード量を減らすことはできます。ですが、あまり大幅に変更してしまうと、リアルタイム用と過去データ用のソースコードが全然違うものになってしまい、2種類のコードを管理しなければならなくなります。

そのため、今回は実践用のコードの内容をできるだけ変更せずに、最小限の修正だけで過去データの検証をすることで、いつでも簡単に実践用(リアルタイム用)のコードに戻せるようにしておきます。

コードの変更点

APIを呼ぶのは最初の1回だけにする

response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc",params = { "periods" : 60 })

先頭で、requests.get()を使って1度だけAPIを使用しています。

実践用のコードでは10秒間に1回APIを使用するため、get_price()の中にrequests.get()を入れていましたが、過去データの検証では1回だけ取得したデータを使うので、requests.get()をget_price()から外して先頭に記述しています。

get_price()の中身を修正する

def get_price(min,i):
	data = response.json()
	last_data = data["result"][str(min)][i]

	return { "close_time" : last_data[0],
		"open_price" : last_data[1],
		"high_price" : last_data[2],
		"low_price" : last_data[3],
		"close_price":last_data[4] }

実践用のコードでは、get_price()は最新のローソク足の価格データを1つだけ返す関数として作成しました。

しかし過去データの検証では、1度だけ取得した価格データを古い順番(時系列順)に試していきます。そのため、i という引数を追加し、指定された i番目のデータを返す関数に修正します。変更点は「i」のところを追加しただけです。

While文の中でiという変数を1ずつ増やす

i = 1
while i < 500:	
	data = get_price(60,i)
	#if文の処理

	i += 1
	time.sleep(0)

実践用のコードでは、While文の中で、10秒に1回APIを使用して最新の価格を取得しにいきます。

しかし過去データの検証では、最初に取得した価格データを先頭から順番(時系列順)に試していくだけです。そのため、While文の中の get_price()に i番目 という意味の変数 i を渡し、ループ処理のたびに i を1ずつ増やす処理に変更します。また10秒待機する必要はないので、sleep()の中を0秒にします。

変更点は以下の部分だけです。

・i = 1 の宣言
・data = get_price(60,i)の部分
・i += 1 を追加
・time.sleep()を0秒に修正

While文のループを500回に限定する

実践用のコードは、リアルタイムの価格を取得し続けるプログラムなので、While True:という無限ループで記述しています。

しかし過去データの検証では、最初に取得した価格データを先頭から順番(時系列順)に試していくだけです。Cryptowatchの価格データの取得件数は、デフォルトでは500件なので、500回ループしたら止まるように、While True:の部分を While i<500: に変更します。

実行結果

これを実行すると以下のようになります。

実際にシグナルが点灯した日のチャートを目で確認しながら、実体の割合、上ヒゲや下ヒゲの割合、上昇率、などのパラメーターを調整していけば、自分の理想のローソク足のパターンでシグナルが点灯するように、コードをカスタマイズすることができます。

今回は1分足で解説していますが、もちろん1時間足や日足でもやり方は同じです。その場合は、最初のAPIの{ periods : } を3600(1時間足)や86400(日足)に変えて使ってください。

なお、勝率の検証などのいわゆる「バックテスト」については、もっと高度な内容になりますが、そちらも今後、解説していく予定です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です