見出し画像

Bot高速化

こんにちは、肉肉カフェを開きたい、ブラッくかふぇです。写真はイチボです。イチボのわりに、サシがあるので、低温でじっくり焼きました。

Bot はロジックも大事なんですが、より早く、ゼロサムゲームの椅子取り合戦に勝たないとダメですよね。
少しでも高速化して差をつけねばということで、
Botの高速化にチャレンジしました。
Python ぶっちゃけ、早くはないです。
でも、私のBotは、Pythonなんですよー。

高速化できる方法を探すと。。。
そもそもC++で書く(C++は仕事以外では触りたくない)
Cython(これ、やっぱりCじゃん)
numba(コード書き換えあんまりいらない。これだ!)

ということで、ここから、numba の話になります。

numba? という方は、こちらから
とても為になります。

題材は、RCIの計算を例に。
まずは、通常実行で、計算時間を計測

import json
import requests
import time
from datetime import datetime, timezone, timedelta
import numpy as np
import pandas as pd

def ord(seq, idx, itv):
    p = seq[idx]
    o = 1
    for i in range(0,itv):
        if p < seq[i]:
            o = o + 1
            #print (seq[i])
    return o
def d(itv,src):
    sum = 0.0
    for i in range(0,itv):
        sum = sum + pow((i + 1) - ord(src, i, itv),2)
        #print (src[o])
        #print (ord(src, i, itv))
    return sum

def rci(itv,src):
    rciM = (1.0 - 6.0 * d(itv,src) / (itv * (itv * itv - 1.0))) * 100.0
    print(d(itv,src))
    return rciM

if __name__ == '__main__':
    itvs = 9# "short interval

    now = datetime.now().strftime('%s')
    res = requests.get('https://www.bitmex.com/api/udf/history?symbol=XBTUSD&resolution=5&from=' + str(int(now)-60*100) + '&to=' + now)
    ohlcv = res.json()
    close = np.array(ohlcv['c'])
    closeR = close[::-1]
    np.set_printoptions(precision=4)
    t3 = 0
    num = 0

    while True:
        t = time.time()
        RCIShort = rci(itvs,closeR)
        t2 = time.time()
        print(t)
        print(t2)
        print("かかった時間は{0}秒です.".format(t2-t))
        t3 = t3 + (t2 - t)
        print(t3)
        num+=1
        print(num)
        print("平均{0}秒です".format(t3/num))
        time.sleep(1)

100回実行して、
平均0.0003258514404296875秒です。

numba を使って実行

from numba import jit

を追加して、高速化した、def の上に@jit と入れるだけ。めちゃくちゃ簡単
で実行すると、初回のみ、遅い。。。
かかった時間は0.31377720832824707秒です.
あれ、遅くない?となり、驚く。。numba が JIT(Just in Time)でコンパイルしているから、どうしても初回は遅い。
2回目以降は、
かかった時間は0.00011801719665527344秒です.
となり、約3倍早い。赤い彗星か!
100回平均だと、
平均0.00014739990234375秒です
だったので、約2倍ですかね。でも、まずまずの速さ。

高速化したコードはこちら

import json
import requests
import time
from datetime import datetime, timezone, timedelta
import numpy as np
import pandas as pd
from numba import jit

@jit
def ord(seq, idx, itv):
    p = seq[idx]
    o = 1
    for i in range(0,itv):
        if p < seq[i]:
            o = o + 1
            #print (seq[i])
    return o

@jit
def d(itv,src):
    sum = 0.0
    for i in range(0,itv):
        sum = sum + pow((i + 1) - ord(src, i, itv),2)
        #print (src[o])
        #print (ord(src, i, itv))
    return sum

def rci(itv,src):
    rciM = (1.0 - 6.0 * d(itv,src) / (itv * (itv * itv - 1.0))) * 100.0
    print(d(itv,src))
    return rciM

if __name__ == '__main__':
    itvs = 9# "short interval

    now = datetime.now().strftime('%s')
    res = requests.get('https://www.bitmex.com/api/udf/history?symbol=XBTUSD&resolution=5&from=' + str(int(now)-60*100) + '&to=' + now)
    ohlcv = res.json()
    close = np.array(ohlcv['c'])
    closeR = close[::-1]
    np.set_printoptions(precision=4)
    t3 = 0
    num = 0

    while True:
        t = time.time()
        RCIShort = rci(itvs,closeR)
        t2 = time.time()
        print(t)
        print(t2)
        print("かかった時間は{0}秒です.".format(t2-t))
        t3 = t3 + (t2 - t)
        print(t3)
        num+=1
        print(num)
        print("平均{0}秒です".format(t3/num))
        time.sleep(1)

@jit のパラメータで、戻り値、引数に型を指定することもできるようで、
さらなる高速化も期待

rci(itvs,closeR) の中身である、
def ord(seq, idx, itv):
def d(itv,src):
にそれぞれ@jit をつけることで高速化しています。どうやら、numbaは for ループ等に効果があるようですね。

連休のお休みを利用して、これから、DeepLearning も少しやらねば!
もともと、Deep Learningの計算早くしたいなーと思って、寄り道してしまいましたw
ちなみに、numba による高速化は、try - except には対応していない為、エラー処理入れるとできないです。

BTCアドレス 3BMEXWoSg5i9zegtEZ3QTEAUDeAV7rKXde