――Lorsque je surfais sur le net, j'ai trouvé un site très utile sur Systre.
Comprenez même dans le système littéraire! Comment démarrer avec le trading automatisé BOT de Bitcoin ――Il a été expliqué d'une manière très facile à comprendre ――Je sens que je peux le faire même si je n'ai aucune expérience avec Systre. «J'étais intéressé, alors j'ai décidé d'écrire un code le week-end pour vérifier la sensation.
Github C'est le code que j'ai écrit cette fois. (Format notebook)
Au fait, avant, Défi de prédire la monnaie virtuelle par LSTM, cela ne fonctionnait pas très bien. Cette fois, j'ai écrit un algorithme simple utilisant des lignes de moyenne mobile sans passer soudainement à l'apprentissage automatique.
--Défini les classes suivantes
import json
import requests
import pandas as pd
import datetime
from pprint import pprint
import time
class PriceGetterCryptwatch():
#Omission
def get_price(self, periods, after=None, before=None, exchange="bitflyer", currency="btcjpy"):
"""
input
periods:Cycle 86400 pour tous les jours
after:Obtenir le graphique après après avec unixTime
before:Obtenir un graphique avant avant avec unixTime
exchange:Échange de devises virtuel
currency:Paire de devises
output
Résultats de l'API:Format JSON
"""
url = "https://api.cryptowat.ch/markets/"+exchange+"/"+currency+"/ohlc?periods="+str(periods)
if after:
after=int(after)
url += "&after=" + str(after)
elif before:
before=int(before)
url += "&before=" + str(before)
print(url)
responce = requests.request("GET", url)
return responce.json()
def apidata_to_dataframe(self, data, periods):
"""
[ CloseTime , OpenPrice , HighPrice , LowPrice , ClosePrice , Volume]
[Date et l'heure,Prix ouvert,Prix élevé,Bas prix,le dernier prix,Le volume]
"""
#La dernière colonne étant inconnue, supprimez-la pour le moment
df = pd.DataFrame(data["result"][str(periods)],columns=[ "CloseTime" , "OpenPrice" , "HighPrice" , "LowPrice" , "ClosePrice" , "Volume", "None"])
df = df.drop("None", axis=1)
#Convertir le temps Unix en temps réel
df["CloseTime"] = df["CloseTime"].map(self.unixtime_to_datetime)
return df
--Si vous l'utilisez, vous obtiendrez le tableau suivant
def save_data(periods):
getter = PriceGetterCryptwatch()
date = getter.datetime_to_obj(2017,1,1)
date = getter.datetime_to_unixtime(date)
# designate start date
data = getter.get_price(periods, after=date)
df = getter.apidata_to_dataframe(data, periods)
start_time = (df["CloseTime"].iloc[0])
last_time = (df["CloseTime"].iloc[-1]) # unixtime
filename = str(start_time) + " - " + str(last_time) + "period " + str(periods)
filename += ".csv"
filename = filename.replace(":", "-")
df.to_csv(filename, index=False, float_format="%.6f")
def update_data(old_filename, periods):
df_old = pd.read_csv(old_filename)
old_size = df_old.shape[0]
# get new data
getter = PriceGetterCryptwatch()
date = getter.datetime_to_obj(2018,1,1)
date = getter.datetime_to_unixtime(date)
# designate start date
data = getter.get_price(periods,after=date)
df = getter.apidata_to_dataframe(data, periods)
df_temp = pd.concat([df_old, df], axis=0)
df_temp["CloseTime"] = pd.to_datetime(df_temp["CloseTime"])
df_save = df_temp.drop_duplicates(subset="CloseTime")
df_save = df_save.sort_values("CloseTime")
df_save = df_save.reset_index(drop=True)
new_size = df_save.shape[0] - old_size
if new_size > 0:
print("NewData : {}".format(new_size))
start_time = df_save["CloseTime"].iloc[0]
last_time = df_save["CloseTime"].iloc[-1] # unixtime
filename = str(start_time) + " - " + str(last_time) + "period " + str(periods)
filename += ".csv"
filename = filename.replace(":", "-")
dir_name = os.path.dirname(old_filename)
filename = os.path.join(dir_name, filename)
df_save.to_csv(filename, index=False, float_format="%.6f")
else:
print("NewData None")
--Exécuter --Lorsque acquis en 1 minute
PERIOD_1MIN = 60
FILENAME_OLD_1MIN = "./Data/2019-11-06 12-45-00 - 2019-11-11 09-03-00period 60.csv"
update_data(FILENAME_OLD_1MIN, PERIOD_1MIN)
--Résultat --Il semble que 258 nouvelles données ont été ajoutées. La mise à jour est rapide car elle dure 1 minute
https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=60&after=1514732400
NewData : 258
CloseTime,OpenPrice,HighPrice,LowPrice,ClosePrice,Volume
2019-11-06 12:45:00,1013343,1013343,1013343,1013343,0.090000
2019-11-06 12:46:00,1013343,1013622,1012862,1013091,2.730759
2019-11-06 12:47:00,1013375,1013839,1013345,1013345,1.170000
...
2019-11-11 13:26:00,981670,982509,981670,982509,0.778839
2019-11-11 13:27:00,982489,982489,982003,982003,0.205953
2019-11-11 13:28:00,982052,982052,982052,982052,0.010000
――Je vais l'élargir
--Création d'une classe d'achat et de vente de pièces de base et en a hérité pour créer un algo commercial ――Le moment où la ligne à court terme croise la ligne à long terme et dépasse ACHAT
Le moment où la ligne à court terme croise la ligne à long terme et tombe en dessous de SELL
Tout d'abord, définissez votre propre JPY et BitCoin, et répétez les achats et les ventes basés sur Argo. ――Il s'agit d'une spécification de joueur qui place tous vos actifs JPY et BitCoin dans chaque transaction.
class TradeBase():
#Omission
def __init__(self, jpy_asset, bitcoin_asset, period):
self.jpy_asset = jpy_asset
self.bitcoin_asset = bitcoin_asset
self.period = period
self.df = None
def buy_coin(self, bitcoin_price, jpy_asset, bitcoin_asset, jpy_buy_amount=None):
"""
Pour le backtesting
"""
if jpy_buy_amount == None:
jpy_buy_amount = jpy_asset
bitcoin_buy_amount = jpy_buy_amount / bitcoin_price
new_jpy_asset = jpy_asset-jpy_buy_amount
new_bitcoin_asset = bitcoin_asset+bitcoin_buy_amount
return new_jpy_asset, new_bitcoin_asset
def sell_coin(self, bitcoin_price, jpy_asset, bitcoin_asset, bitcoin_sell_amount=None):
"""
Pour le backtesting
"""
if bitcoin_sell_amount== None:
bitcoin_sell_amount = bitcoin_asset
jpy_sell_amount = bitcoin_price * bitcoin_sell_amount
new_jpy_asset = jpy_asset + jpy_sell_amount
new_bitcoin_asset = bitcoin_asset-bitcoin_sell_amount
return new_jpy_asset, new_bitcoin_asset
class TradeWithMovingAverage(TradeBase):
"""
Lors de l'achat et de la vente uniquement à l'intersection de deux types de moyenne mobile
"""
def __init__(self, jpy_asset, bitcoin_asset, period, period_ma_type1, period_ma_type2):
super().__init__(jpy_asset, bitcoin_asset, period)
self.period_ma_type1 = period_ma_type1
self.period_ma_type2 = period_ma_type2
self.rolling_win_type1 = int(period_ma_type1 / period)
self.rolling_win_type2 = int(period_ma_type2 / period)
# for trade func
self.prev_mean_type1 = None
self.prev_mean_type2 = None
self.jpy_asset_result = []
self.data = None
def judge_sell_or_buy(self, new_mean_fast, prev_mean_fast, new_mean_slow, prev_mean_slow):
"""
Jugement d'achat et de vente en regardant la ligne de moyenne mobile
"""
if prev_mean_fast > prev_mean_slow:
if new_mean_fast < new_mean_slow:
return "SELL"
else:
return "NOTHING"
elif prev_mean_fast < prev_mean_slow:
if new_mean_fast > new_mean_slow:
return "BUY"
else:
return "NOTHING"
else:
return "NOTHING"
def trade(self, init_var=True):
if self.data is None:
print(" Data is None")
return
if init_var:
self.prev_mean_type1 = None
self.prev_mean_type2 = None
self.jpy_asset_result = []
mean_type1 = None
mean_type2 = None
last_sell_jpyasset = None
for i, value in enumerate(self.data):
# Average
if i > self.rolling_win_type1:
mean_type1 = self.data.iloc[int(i-self.rolling_win_type1):i].mean()
if i > self.rolling_win_type2:
mean_type2 = self.data.iloc[int(i-self.rolling_win_type2):i].mean()
if mean_type1 is None or mean_type2 is None:
self.jpy_asset_result.append(self.jpy_asset)
continue
# Trade
bitcoin_price = value
if self.prev_mean_type1 and self.prev_mean_type2:
judge = self.judge_sell_or_buy(mean_type1, self.prev_mean_type1,
mean_type2, self.prev_mean_type2)
if judge == "SELL":
if self.bitcoin_asset > 0:
self.jpy_asset, self.bitcoin_asset = self.sell_coin(bitcoin_price, self.jpy_asset, self.bitcoin_asset)
last_sell_jpyasset = self.jpy_asset
elif judge == "BUY":
if self.jpy_asset > 0:
self.jpy_asset, self.bitcoin_asset = self.buy_coin(bitcoin_price, self.jpy_asset, self.bitcoin_asset, jpy_buy_amount=self.jpy_asset)
else:
pass
self.prev_mean_type1 = mean_type1
self.prev_mean_type2 = mean_type2
self.jpy_asset_result.append(self.jpy_asset)
self.last_sell_jpyasset = last_sell_jpyasset
print("Result: Jpy{:.1f} bitcoin{:.4f} (LAST JPY: {})".format(self.jpy_asset, self.bitcoin_asset, self.last_sell_jpyasset))
return self.jpy_asset, self.bitcoin_asset
jpy = 10000
bitcoin = 0
period = 60*60*4 #4 heures
trader = TradeWithMovingAverage(jpy_asset=jpy, bitcoin_asset=bitcoin, period=period,
period_ma_type1=period*3, period_ma_type2=period*5)
#Ensemble de données(Manuel)
trader.df = df
trader.data = df["ClosePrice"]
trader.trade()
trader.show_trade_result()
Il a plus que triplé par rapport au point de départ de 10 000 yens et semble fonctionner de manière inattendue.
--J'ai essayé de l'utiliser pour les dernières données (2019/9 ~ 2019/11)
«J'ai pu voir avec mes yeux que le trading mécanique semble être plus stable sans biais que les humains. «Je suis content d'avoir eu l'idée de créer un algorithme de trading. «Je pense que nous allons apporter des améliorations qui intègrent d'autres indicateurs. ――Il semble qu'il faudra beaucoup de temps pour l'utiliser dans la pratique --Apprentissage approfondi, je voudrais intégrer un apprentissage amélioré dans l'algorithme de jugement commercial. --Merci pour la lecture.
Recommended Posts