見出し画像

Pythonでチャート分析のための正確な時間測定に挑戦してみた

正確な時間の測定 

どんなものでも、分析をするには正確であることが必要だ。

でも、プログラムを作っている人ならわかると思うけど、PCの状態に応じて時間はずれてゆく。

携帯電話でプログラムを書いているボクなんかはますますズレる。

前回、オカルト的に仮想通貨のチャートを20秒単位で分析する必要があると書いた

今回は、プログラミング言語Pythonで正確な時間の測定に挑戦しようと思う。

Pythonで時間測定

まずは、前回まで作ったコードはこれ。

# -*- coding: utf-8 -*- #
"""
We crush capitalism.
"""
import pybitflyer
import csv
import time

while True:
   BTC_tick = pybitflyer.API().ticker(product_code="BTC_JPY")
   print("BTC_timestamp : " + str(BTC_tick["timestamp"]))
   print("BTC_ltp : " + str(BTC_tick["ltp"]))
   print("BTC_best_bid : " + str(BTC_tick["best_bid"]))
   print("BTC_best_ask : " + str(BTC_tick["best_ask"]))

   ETH_tick = pybitflyer.API().ticker(product_code="ETH_JPY")
   print("ETH_timestamp : " + str(ETH_tick["timestamp"]))
   print("ETH_ltp : " + str(ETH_tick["ltp"]))
   print("ETH_best_bid : " + str(ETH_tick["best_bid"]))
   print("ETH_best_ask : " + str(ETH_tick["best_ask"]))

   with open('furture.csv','a',newline=''as files:
      writer = csv.writer(files)
      writer.writerow(['TIME',str(ETH_tick["timestamp"]),'ltp',str(ETH_tick["ltp"]),'bid',(ETH_tick["best_bid"]),'ask',str(ETH_tick["best_ask"])])
   time.sleep(10)	

前回、timeモジュールをimportして、最後の行で次のコードを書いていたと思う。これは、10秒間プログラムを休ませる命令だ。

time.sleep(10)	

でも、ボクがしたいのは、ループ処理している全てのプログラムを10秒単位で実行し、20秒を一単位にしてチャートを分析することだ。
誤差が大きければ計測には致命的。だけど、Pythonで時間を図るにはどうすればいいだろう。

time.time()はUNIXエポックを基準点とした経過秒数を返す関数で、現在時刻を取得するのに便利です。
ただ、返り値の単位が「秒」、かつ浮動小数点型のため、何時何分なのかイマイチ分かり難いです。
そこで、datetimeモジュールを使って見やすく変換する方法についても紹介します。
また、この関数は、あるコードブロックの処理時間を計測するのに使われることもありますが、使う際には少し注意が必要です。そのあたりも併せてまとめてみました。

Unixエポックとは、協定世界時のことをいう。コンピュータの時刻表現の一つだ。時差の調整をしていなければ、日本時間よりも9時間早い時間が表示される。

UNIX時間における基準となる時間であり「1970年1月1日午前0時0分0秒(UTC)」のことです。(中略)
UTCは「日本時間から9時間引いた時間」です。
日本語では「協定世界時」と表現されます。
(中略)
協定世界時 (UTC)(英:Coordinated Universal Time)とは今の世界で標準時として使っている時間でありセシウム原子の振動数をもとに導き出す時間です。ただし、普通に生活する分には日本時間から9時間引いた時間のことだと思って良いです。

じつはコンピュータは関数によって精度が違う。よく使われるtime.time()だと1/60秒の精度だ。これだと、10秒から20秒の間でチャート分析をすると、10分も計測すれば致命的にずれてしまう。

公式ドキュメントによると,Python 3.3 以前の Windows では time.clock() はマイクロ秒,time.time() は 1/60 秒の精度で,Unix では time.clock() は 1/100 秒,time.time() はそれ以上の精度らしいです.解釈が間違っていなければ Windows で実行するか macOS で実行するかによって使う関数を変えなければならないという...
どちらにしてもデフォルトでは CPU 時間で計測しないため,CPU 上の他のプロセスの干渉を受けるようです.また,Unix では time.clock() を使うと CPU 時間で計測できるようですが,さっき 1/100 秒って言ってなかったっけ?という感じです.

それでは、Pythonの関数でもっと正確に測定する方法はないだろうか。

Pythonでは「time.time」および「time.perf_counter」で経過時間を測定することができます。
プログラムの実行時間を計測したり、ボトルネックを特定する場合に経過時間を測定するのは効果的です。

perf_counter()関数だと、正確に測定することはできるだろうか。悩んでいるよりも、実際に測定をしてみよう。

perf_counter() 関数は、システム時間の最も正確な測定値を提供します。perf_counter() 関数はシステム全体の時間を返し、スリープ時間を考慮に入れます。perf_counter() 関数を使用して、関数の実行時間を計算することもできます。次のコード例は、Python の perf_counter() 関数を使用して関数の実行時間を計算する方法を示しています。

早速、perf_counter() 関数を使ってみる。import timeの下に次のコードを記入する。これは、Start_timeという引数に、正確な時間を代入している。

import time
"""
初期設定
"""
Start_time = time.perf_counter()

次に、whileの関数の下に次のコードを記入する。
print()という関数は、プログラムの結果を表示させる。今回は、二つの時間を表示させて、プログラムによる時間の誤差を確認している。あくまで、誤差を確認するので、年月日に加工しないで秒での表示だ。

while True:
   print(Start_time)
 print(time.perf_counter())

そして、一番下のtime.sleep(10)を次のコードに書きかえる。
1段目の文は、最初に代入した時間からちょうど10秒後に調整した時間を待機させるコードだ。
2段目の段は、最初に代入した時間に10秒を加えている。

time.sleep((10 + Start_time ) - time.perf_counter())
Start_time = Start_time + 10

これで、時間を測定しよう。時間の誤差はどれくらいになるだろうか。プログラムでの時間の誤差は0.001秒程度。1000回プログラムを動かして1秒ずれるがどうかだ。チャート分析には十分だろう。

CSVファイルに出力されたイーサリアムのタイムスタンプを見てみると、±1秒程度の誤差の間を振幅している。これくらいの誤差ならチャート分析に使えるレベルだと思える。

今回、作成したしたコードはこちら。次は、分析方法をどうするかだ。

# -*- coding: utf-8 -*- #
"""
We crush capitalism.
"""

import pybitflyer
import csv
import time
"""
初期設定
"""
Start_time = time.perf_counter()

while True:
   print(Start_time)
   BTC_tick = pybitflyer.API().ticker(product_code="BTC_JPY")
   print("BTC_timestamp : " + str(BTC_tick["timestamp"]))
   print("BTC_ltp : " + str(BTC_tick["ltp"]))
   print("BTC_best_bid : " + str(BTC_tick["best_bid"]))
   print("BTC_best_ask : " + str(BTC_tick["best_ask"]))

   ETH_tick = pybitflyer.API().ticker(product_code="ETH_JPY")
   print("ETH_timestamp : " + str(ETH_tick["timestamp"]))
   print("ETH_ltp : " + str(ETH_tick["ltp"]))
   print("ETH_best_bid : " + str(ETH_tick["best_bid"]))
   print("ETH_best_ask : " + str(ETH_tick["best_ask"]))

   with open('furture.csv','a',newline=''as files:
      writer = csv.writer(files)
      writer.writerow(['TIME',str(ETH_tick["timestamp"]),'ltp',str(ETH_tick["ltp"]),'bid',(ETH_tick["best_bid"]),'ask',str(ETH_tick["best_ask"])])
   time.sleep((10 + Start_time ) - time.perf_counter())
   Start_time = Start_time + 10

目次

前の記事

この記事が気に入ったらサポートをしてみませんか?