【コピペで完成】Qiitaの中で1番早く?!仮想通貨自動売買BOTを誰でも体験【シストレ超々入門】

#概要
というわけでよくある自動売買bot系の記事です
とりあえずDockerとか難しい(?)とこから入らないで
秒で環境ができて、即動かせるコードを公開したいです
逆に言えば僕が勉強初め時にとりあえず欲しかったコードです。。。

「とりあえず自動売買シュミレータレベルで動かしたい人」向け
動かなかったらごめんなさい

#目的
何でもいいから、とにかく秒で動く自動売買系のコードが欲しい人向けにコードを公開する


#完成イメージ
今回はこのグラフが出来たら成功です。上のグラフが相場で、下のグラフが損益のグラフです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181863/12670741-3b57-cf39-2299-2197a9ee8b1a.png)

#まずはコピペでコードを動かそう
以下を開いて
https://colab.research.google.com/
+コードのボタンを押して以下をコピペ
※Googleログインは必須

```python
!pip install git+https://github.com/MtkN1/pybybit.git
!pip install rich
!pip install pandas
!pip install numpy
!pip install tqdm
!pip install matplotlib

from datetime import datetime
from rich import print
import math
import pybybit
import pandas as pd
import numpy as np
from tqdm import tqdm
from matplotlib import pyplot as plt

#--------------------設定項目--------------------
bybit = pybybit.API(testnet = False)

symbol    = "BTCUSD"
chart_min = 60 # 時間軸(1 3 5 15 30 60 120 240 360 720 )
start     = '2022/01/01 09:00' # ローソク足取得開始時刻
get_days  = 30 # 取得数[日]

#====================価格データ取得(APIから)===================
def get_price_from_API(chart_min,start):
    get_start = int(datetime.strptime(start,'%Y/%m/%d %H:%M').timestamp()) # タイムスタンプ変換
    price = []
    req_times = math.ceil(1440/chart_min*get_days/200)

    #200*n本のローソク足を取得して、price[]に入れる
    for o in tqdm(range(req_times), desc = "{}分足データ取得中".format(chart_min)): # ()内の回数だけデータを取得
        data = bybit.rest.inverse.public_kline_list(
                symbol   = symbol,
                interval = chart_min,
                from_    = get_start
                ).json()

        #priceに取得したデータを入れる
        for i in data["result"]:
            price.append(i)

        #200本x足の長さ分だけタイムスタンプを進める
        get_start += 200*60*chart_min

    df = pd.DataFrame(price)
    df.open_time = pd.to_datetime(df.open_time*10**9,)
    df = df.set_index('open_time').tz_localize('UTC').tz_convert('Asia/Tokyo')
    df.drop(["symbol","interval","volume","turnover"],axis = 1,inplace=True)
    df = df.astype('float')

    return df[:int(1440/chart_min*get_days)]

#====================テーブル作成===================
def create_table(df):
    # MAの計算
    df["7MA"] = round(df.close.rolling(7).mean(),2)
    df["28MA"] = round(df.close.rolling(28).mean(),2)

    # 売買シグナルの計算
    df["Buy"] = np.where((df["7MA"].shift(1)<df["28MA"].shift(1))&(df["7MA"]>df["28MA"]),True,False)
    df["Sell"] = np.where((df["7MA"].shift(1)>df["28MA"].shift(1))&(df["7MA"]<df["28MA"]),True,False)

    # 注文・ポジションの計算
    df["order"] = 0
    df["order"] = df.order.mask(df.Buy==True,1)
    df["order"] = df.order.mask(df.Sell==True,-1)
    df["pos"] = df.order.cumsum()

    # 損益の計算
    df["accrue_return"] = df.close.diff(-1)*-1
    df["profit"] = df.accrue_return*df.pos
    df["pnl"] = df.profit.cumsum()

    return df

#====================グラフ作成===================
def plot(df):
    plt.figure() # グラフの表示エリアを作成
    plt.suptitle("Bybit [{0}min] {1} to {2}"
                    .format(chart_min,df.index[0].strftime("%m/%d %H:%M"),df.index[-1].strftime("%m/%d %H:%M")))

    # 終値チャート
    plt.subplot(2,1,1)
    plt.plot( df.index, df.close ) # X軸、Y軸の値を指定
    plt.ylabel("{}".format(symbol), fontsize=25) # Y軸のラベル名

    # 損益グラフ
    plt.subplot(2,1,2)
    plt.plot( df.index, df.pnl) # X軸、Y軸の値を指定
    plt.xlabel("open_time", fontsize=25) # X軸のラベル名
    plt.ylabel("pnl", fontsize=25) # Y軸のラベル名

    plt.show() # グラフの表示

#====================メイン処理===================
ohlc = get_price_from_API(chart_min,start)
df = create_table(ohlc)
print(df)
plot(df)
```

#補足
Google Colab (Colaboratory)には、最初から以下のライブラリがあるようでした
なのでいきなりインポートでよさそうです。他の環境で動かす際はインストールしてください
import math

#解説
実はこれ参考元の記事があって（現在はサーバーが落ちていましたURLは最下部へ）、僕自身完璧には理解してないので引用しながら大事なところだけ解説したいです

##注目ライブラリー→「pybybit」
最初の1行目のインストールにあるのでお気づきの方いたかもしれませんが、このライブラリは簡単に言うと
仮想通貨取引所[バイビット](https://www.bybit.com/ja-JP/)の「公式ＡＰＩ使いにくいんじゃ！わしがみんなのため最高のライブラリ作ったる」（※分かりやすくなるように言い換えました）
と作られたもののようです

>フルマネージドを目指した自動取引ライブラリです。
>リニア契約(BTCUSDT)・先物契約対応、テスト環境(testnet)対応、WebSocket完備。
>汎用ライブラリの ccxt とは違い、Bybitが提供しているAPIを全て利用できます。
>(注文送信・キャンセル、ポジション取得、残高参照、ファンディングレート取得、マーク価格取得...)
>つまり、このライブラリをインストールすればBybitで自動取引する事が可能です。

詳しくは「まちゅけん」さん、の「ｎｏｔｅ」をご覧ください。
https://note.com/mtkn1/n/n9ef3460e4085

その他のライブラリは通常使われるライブラリのようなので割愛します

##ストラテジー（売買戦略）について
引用元記事より
>指標を計算する
>ローソク足データを用意出来たら、指標を用意しましょう。
>今回は例として、 7MAが28MAを上回ったら買い、下回ったら売りというロジックにしてみましょう。
>（適当なので利益が出るかはわかりません。）

MA＝[移動平均線](https://www.google.com/search?q=%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87%E7%B7%9A%EF%BC%88Moving+Average%EF%BC%9AMA%EF%BC%89&oq=%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87%E7%B7%9A%EF%BC%88Moving+Average%EF%BC%9AMA%EF%BC%89&aqs=chrome..69i57j0l3.416j0j4&sourceid=chrome&ie=UTF-8)



```
    # MAの計算
    df["7MA"] = round(df.close.rolling(7).mean(),2)
    df["28MA"] = round(df.close.rolling(28).mean(),2)

    # 売買シグナルの計算
    df["Buy"] = np.where((df["7MA"].shift(1)<df["28MA"].shift(1))&(df["7MA"]>df["28MA"]),True,False)
    df["Sell"] = np.where((df["7MA"].shift(1)>df["28MA"].shift(1))&(df["7MA"]<df["28MA"]),True,False)
```

###ポイント→短期線が長期線を下から上へ突き抜ければ買いサイン
などと言われるそうなので、
(7MA=)7日間移動平均線（短期線）が28日間移動平均線（長期線）を突き抜けたらdf["Buy"]に条件式をつっこんでおくと、
これで買い設定できるようです。売りも同様

###条件式
```
np.where((df["7MA"].shift(1)<df["28MA"].shift(1))&(df["7MA"]>df["28MA"]),True,False)
```
初見いまいちわからなかったので分解しましょう

```
np.where(
```

import numpy as np
インポートした「numpy」ですね。詳しくはほかの記事へ

https://qiita.com/KozoNomamoto/items/08ed3cb40bce58fbae8e

whereも他の記事へ

https://note.nkmk.me/python-numpy-where/

```
  (df["7MA"].shift(1)<df["28MA"].shift(1)) & (df["7MA"]>df["28MA"])
```

[shift](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.shift.html)
>インデックスを任意の周期数だけシフトさせることができます

ピンと来た人もいるかもしれないが、短期線と長期線を1つ分動かした数値を比較して長期線の方が大きい
＆かつ
今の短期線と長期線を比較して短期線の方が大きい場合つまり

[ゴールドクロス](https://www.google.com/search?q=%E3%82%B4%E3%83%BC%E3%83%AB%E3%83%89%E3%82%AF%E3%83%AD%E3%82%B9%E3%80%80fx&sxsrf=APq-WBuoIVpMkQa7ufZIp0WapF3v6bZd5g%3A1643898948780&ei=ROj7YYWLL8yymAX64aKIBg&ved=0ahUKEwiFvY3n4OP1AhVMGaYKHfqwCGEQ4dUDCA4&uact=5&oq=%E3%82%B4%E3%83%BC%E3%83%AB%E3%83%89%E3%82%AF%E3%83%AD%E3%82%B9%E3%80%80fx&gs_lcp=Cgdnd3Mtd2l6EAMyBAgAEB46BwgjELADECc6BwgAEEcQsAM6BwgAEIAEEARKBAhBGABKBAhGGABQmQhY5BFgwxNoAXACeACAAYABiAHdApIBAzEuMpgBAKABAcgBCsABAQ&sclient=gws-wiz)が発生したら買え、という条件のようだ

```
,True,False)
```
条件を満たす場合はTrue, 満たさない場合はFalseとする

ということで、買いの条件を設定していることが分かった
売りは逆なので省略します

一旦以上です
よかったらＬＧＴＭよろしくお願いいたします。
ＬＧＴＭが多ければさらに詳しく書くかも
最下部の元記事のＷＥＢアーカイブを見るとほとんどわかるかと思います

#あとがき
参考にして動かない記事が多すぎて僕が苦しんだので、
これ以上苦しむ人を減らすためにこの記事を作成しました。
自動売買botを始める人のとっかかりになればと思います

なので動いたコードの記事を貼り付けるでも結構いいのかもと思った次第です
ちなみに参考にしたコードの記事は現在は、落ちてるようでした
https://www.mamu-trade.com/backtest/ 

なのでＷＥＢアーカイブのURLを張っておきます
https://web.archive.org/web/20211218225052/https://www.mamu-trade.com/backtest/

あと、ローカルのpython環境と損益の結果が違った謎が残りました。実際これで負けても責任とれないので「自己責任」でお願いします