見出し画像

botの損益を可視化、管理しよう!

 どうも、Salterです。いきなりですがbotの損益管理って大事ですよね。botの損益を確認することはロジックにどれくらい期待値があるのか、ロットはあとどのくらい余裕があるのか等を現在の相場環境に対して正確に確認するために重要なプロセスだと考えられます。そこで今回は私が用いているbotの損益の確認方法について書いていこうと思います。

・前提

まず、前提として
・損益曲線を任意の期間について可視化できる
・なるべくインタラクティブな画面で見たい
・サーバーを建てるのは管理が面倒なのでやりたくない

 この3つを満足するような方法について考えます。3つ目については、influxdb等での管理、grafana等のサービスでの可視化を指しています。この方法で管理できれば非常にインタラクティブでかっこいい可視化ができるのですが、VPS初心者でありサーバーをあまり建てたくない自分的にはもう少し簡単に済ませる方法がないかと考えました。

・方法

方法は以下の通りです
1. botに定期的にcsvファイルを更新してもらう
2. 更新したファイルをgoogle driveに送る
3. colabで損益管理用のnotebookを開く

ポイントとしては、
・2で、1でローカルに出力したファイルをgoogle driveに送るスクリプトを作成する

・3で、plotlyを使うことでできるだけインタラクティブでかっこいい管理画面を再現する

ということです。
 1については、botごとに出力するcsvファイルの構造が変わると思われるので割愛しますが、私の場合だと以下のようなものになります。


一応マスクしてる部分もあります

・2について

2ではpydriveにより、googleのapiを用いて自分のアカウントのgoogle driveにcsvファイルを送るスクリプトを1の更新と合わせて定期的に実行させます。以下に参考にしたサイトと、スクリプトを載せておきます。

スクリプト

import pandas as pd
from pydrive.drive import GoogleDrive
from pydrive.auth import GoogleAuth

# botのデータをorder_id.csvファイルとする
# Googleサービスを認証
gauth = GoogleAuth()

# 資格情報ロードするか、存在しない場合は空の資格情報を作成
gauth.LoadCredentialsFile("mycreds.txt")

# Googleサービスの資格情報がない場合
if gauth.credentials is None:
    # ユーザーから認証コードを自動的に受信しローカルWebサーバーを設定
    gauth.LocalWebserverAuth()
# アクセストークンが存在しないか、期限切れかの場合
elif gauth.access_token_expired:
    # Googleサービスを認証をリフレッシュする
    gauth.Refresh()
# どちらにも一致しない場合
else:
    # Googleサービスを承認する
    gauth.Authorize()
# 資格情報をtxt形式でファイルに保存する
gauth.SaveCredentialsFile("mycreds.txt")

# Googleドライブの認証処理
drive = GoogleDrive(gauth)

file_id = drive.ListFile({'q': 'title = "order_id.csv"'}).GetList()[0]['id']
rf = drive.CreateFile({'id': file_id})
rf.Delete()

directory = r'order_id.csv'
path = r'~\order_id.csv'

f = drive.CreateFile({'title': directory})
f.SetContentFile(path)
f.Upload()

f = None

・3について

3では、google driveに.ipynbファイルを作成し、
Ⅰ. driveをマウント
Ⅱ. 2のデータを読み込んで整形
Ⅲ. 可視化
のような手順で実行するように組んであげればよいです。

notebookの例

# driveをマウント
from google.colab import drive
drive.mount('/content/drive')

# データの整形と出力

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import time, requests
from dateutil.parser import parse
from datetime import datetime, timedelta
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import warnings
warnings.simplefilter('ignore')
%matplotlib notebook

order_id = pd.read_csv(r'/content/drive/My Drive/order_id.csv')
order_id = order_id.set_index('Unnamed: 0')
order_id.index.name = 'timestamp'
order_id.index = np.array([parse(x) for x in order_id.index])
order_id = order_id.dropna()
order_id = order_id[order_id['result'] == 1]
order_id['ret'] = (order_id['exit_price'] - order_id['entry_price']) * order_id['entry_side'] * order_id['executed_size']
order_id['cum_ret'] = order_id['ret'].cumsum()
order_id.index.name = 'timestamp'
order_id = order_id.reset_index()
order_id['timestamp'] = order_id['timestamp'].dt.floor('min')
order_id = order_id.set_index('timestamp')

gridcolor = 'rgb(192, 229, 232)'

order_id['zero'] = 0
fig = make_subplots(rows=1, cols=1, shared_xaxes=True, vertical_spacing=0.3)
fig.add_trace(go.Line(x=order_id.index, y=order_id['cum_ret'], name='profit_cum', line={'color': 'rgb(238, 77, 90)'}))
fig.add_trace(go.Bar(x=order_id.index, y=order_id['ret'], marker_line_width=1.6, name='profit/trade', marker={'color': 'black'}))
fig.update_layout(title={'text': 'ALL PROFIT  {0}.0'.format(round(order_id['cum_ret'].values[-1])), 'font': {'color': gridcolor}}, height=360, width=600, plot_bgcolor='rgb(59, 73, 108)', paper_bgcolor='rgb(59, 73, 108)', legend={'font': {'color': gridcolor}})
fig.update_yaxes(color=gridcolor, linecolor=gridcolor, gridcolor=gridcolor)
fig.update_xaxes(color=gridcolor)
fig.show()

daily_pnl = order_id[['ret']].resample('1d').sum()
daily_pnl['cum_ret'] = daily_pnl['ret'].cumsum()
daily_pnl['zero'] = 0
gridcolor = 'rgb(192, 229, 232)'

fig2 = make_subplots(rows=1, cols=1, shared_xaxes=True, vertical_spacing=0.3)
fig2.add_trace(go.Line(x=daily_pnl.index, y=daily_pnl['cum_ret'], name='profit_cum', line={'color': 'rgb(238, 77, 90)'}))
fig2.add_trace(go.Bar(x=daily_pnl.index, y=daily_pnl['ret'], name='profit/day', marker={'color': 'black'}))
fig2.update_layout(title={'text': 'DAILY PROFIT', 'font': {'color': gridcolor}}, height=340, width=600, plot_bgcolor='rgb(59, 73, 108)', paper_bgcolor='rgb(59, 73, 108)', legend={'font': {'color': gridcolor}})
fig2.update_yaxes(color=gridcolor, linecolor=gridcolor, gridcolor=gridcolor)
fig2.update_xaxes(color=gridcolor)
fig2.show()

実行結果


このような感じで出力されます。また、plotlyを使っているので期間を絞ったりなどある程度インタラクティブに表示できます。

 .ipynbファイルは、スマホではchromeでgoogle driveから開くことで自然にcolabから実行できるので外出先などでスマホから結果を眺めることもできます。

・感想

 いかがだったでしょうか?確かにサーバーを建てた方が更新頻度も高いですし、あのgrafana特有のかっこいい感じは憧れますが、手軽にある程度のかっこよさもあるという点ではこの方法も悪くはないのではないでしょうか?個人的にはしばらくはこの方法で管理しようかなと考えています。

いいなと思ったら応援しよう!