akiyoko blog

akiyoko の IT技術系ブログです

「fin-pyもくもく会 #10」に参加してきました

主催

fin-py

会場

株式会社インタートレード
東京都中央区新川一丁目17番21号 茅場町ファーストビル3階

Twitter

twitter.com



 

全体の感想など

fin-py は今回で 3回目の参加となりました。

Python は業務で7年ほど&プライベートでもちょくちょく触っているのでそこそこ使いこなせますが、これまで金融業界の経験もないし、個人的にほとんど投資をしたことがないので、Finance の部分は素人同然。発表のときに「約定」を「やくてい」と読んでしまうほどのレベルです。。


まあ、金融業界にいなくても独学で十分という話もありますが。。


あと今回は参加者が多くてビックリしました。特に初参加の方が多かったようです。Quantopian 関連の人が多かったのでしょうか、詳しくはよく分かりません。



《過去記事》
akiyoko.hatenablog.jp

akiyoko.hatenablog.jp



 

やりたかったこと

bitFlyer の BTC-FX API を使ってトリガー検知

bitFlyer Lightning FX(ビットコイン FX) では、預入証拠金に対して最大15倍の取引ができるのが特徴です。最低取引金額が 0.001 BTC になっているため、1BTC=100万円として 1,000 円(レバレッジ15倍なら預入証拠金は約67円)から取引ができることになります。


bitFlyer ビットコインを始めるなら安心・安全な取引所で
bitFlyer ビットコインを始めるなら安心・安全な取引所で


背景としては、この一年の仮想通貨のトレンドとして、

Ripple(3月上旬)
アルトコイン(〜6月中旬)
草コイン(〜7月?)
ICO(〜9月中旬)
ハードフォーク(〜11月?)
チャイナショック(9月初旬) ⇒ アルトコインが焼かれる
CME先物発表(10月下旬) ⇒ アルトコインが焦土に
取引所増加
BTC-FX ⇐ 今ココ!?


みたいな流れがあったりするので、ちょっと触ってみようかと(まだ触ったことはありません)。


 

やったこと

  • FX 戦士たちの戦略調査
  • bitFlyer Lightning(FX取引所)を眺めてみる
    • いろんな音が鳴ってた ♪
  • pybitflyer 触ってみた
  • ccxt で書いてみた
  • テクニカル指標を扱うライブラリ「TA-Lib」を使ってグラフ書いてみた

 

環境
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.6
BuildVersion:   16G1036

$ python --version
Python 3.5.2 :: Anaconda 4.2.0 (x86_64)


 

TA-Lib のインストール

テクニカル指標を扱うライブラリ。
GitHub - mrjbq7/ta-lib: Python wrapper for TA-Lib (http://ta-lib.org/).

$ brew install ta-lib
$ pip install TA-lib

TA-Lib (0.4.10)

「error: command '/usr/bin/clang' failed with exit status 1」とのエラーが出るので、まず先に「brew install ta-lib」が必要。

(参考)python - /usr/bin/clang command failing trying to pip install TA-lib on MacOS - Stack Overflow


 

pybitflyer のインストール

id:yag_ays さん作の bitFlyer REST API のラッパーライブラリ。
bitFlyer LightningのAPIをPythonから使えるパッケージ「pybitflyer」を作りました - おおかみ山

$ pip install pybitflyer

pybitflyer (0.1.7)


使ってみる。

import pybitflyer

exec(open('env.py', 'rb').read())

api = pybitflyer.API(
    api_key=BITFLYER_KEY,
    api_secret=BITFLYER_SECRET,
)
api.board(product_code='FX_BTC_JPY')

こんな感じで、板情報が取れます(それぞれ100件くらい)。

{'asks': [{'price': 942400.0, 'size': 0.00310928},
  {'price': 942497.0, 'size': 0.60458056},
  {'price': 942498.0, 'size': 0.04},
  ...],
 'bids': [{'price': 942212.0, 'size': 0.0521},
  {'price': 942152.0, 'size': 0.3},
  {'price': 942151.0, 'size': 0.22},
  ...],
 'mid_price': 942306.0}


 

ccxt で書いてみた

pybitflyer とほぼ同じことが書けます。

import ccxt
from pprint import pprint

exec(open('env.py', 'rb').read())

ex = ccxt.bitflyer({
    'apiKey': BITFLYER_KEY,
    'secret': BITFLYER_SECRET,
})

pprint(ex.fetch_ticker('FX_BTC_JPY'))
print('-' * 50)
pprint(ex.fetch_order_book('FX_BTC_JPY'))
{'ask': 1019470.0,
 'average': None,
 'baseVolume': 234473.73139995,
 'bid': 1019144.0,
 'change': None,
 'close': None,
 'datetime': '2017-11-26T12:56:20.000Z',
 'first': None,
 'high': None,
 'info': {'best_ask': 1019470.0,
          'best_ask_size': 0.0152,
          'best_bid': 1019144.0,
          'best_bid_size': 1.4489,
          'ltp': 1019144.0,
          'product_code': 'FX_BTC_JPY',
          'tick_id': 10554736,
          'timestamp': '2017-11-26T12:56:20.9',
          'total_ask_depth': 8018.9239892,
          'total_bid_depth': 11740.4605367,
          'volume': 249894.26662009,
          'volume_by_product': 234473.73139995},
 'last': 1019144.0,
 'low': None,
 'open': None,
 'percentage': None,
 'quoteVolume': 249894.26662009,
 'symbol': 'FX_BTC_JPY',
 'timestamp': 1511700980000,
 'vwap': None}
--------------------------------------------------
{'asks': [[1019470.0, 0.0152],
          [1019475.0, 0.0152],
          [1019494.0, 0.2008],
          ...,
          [1735257.0, 0.79804842]],
 'bids': [[1019144.0, 1.4489],
          [1019143.0, 2.331],
          [1019140.0, 0.01],
          ...,
          [95000.0, 2.0]],
 'datetime': '2017-11-26T12:56:22.000Z',
 'timestamp': 1511700981575}


しかしながら、pybitflyer と同じく 100件ほどしか板情報が取れないため、例えばボリンジャーバンドを計算するための ticker の情報はどうやって収集すればいいの?というのが懸念点。



 

TA-Lib を使ってグラフ書いてみた

とりあえず、さくらのクラウドサーバ上の MongoDB に格納している ticker データからグラフ作ってみました。

前回の反省を活かし、Jupyter Notebook で。

% matplotlib inline

from datetime import datetime, timedelta

import matplotlib.pyplot as plt
import pandas as pd
import talib
from pymongo import MongoClient, ASCENDING
from sshtunnel import SSHTunnelForwarder

plt.style.use('ggplot')
pd.options.display.max_rows = 20

now = datetime.now()
df = None

with SSHTunnelForwarder(
    '153.xxx.xxx.xxx',
    ssh_username='ubuntu',
    ssh_pkey='/Users/akiyoko/.ssh/sakura.pem',
    remote_bind_address=('127.0.0.1', 27017)
) as server:
    # server.start()
    print(server.local_bind_port)

    client = MongoClient('127.0.0.1', server.local_bind_port)
    db = client['bittrex']
    collection = db['tickers']

    records = list(collection.find(
        {
            'symbol': 'BTC',
            'timestamp': {'$gte': now - timedelta(minutes=60 * 24)},
        },
        {'_id': False},
    ).sort('timestamp', ASCENDING))

    df = pd.DataFrame(records)
    # Need?
    # https://stackoverflow.com/a/17328858/8426544
    #df = df.set_index(pd.DatetimeIndex(df['timestamp']))

print(df.dtypes)

df['sma'] = talib.SMA(df['last'].values, timeperiod=12)
print(df)

ax = df.plot(x='timestamp', y='last')
df.plot(ax=ax, x='timestamp', y='sma', secondary_y=True)


f:id:akiyoko:20171126220525p:plain





 

LT

pandas はデータをリサンプリングできる。例えば、1分足から5分足へ。

例えば、こんな感じ。

% matplotlib inline

import matplotlib.pyplot as plt
import pandas as pd
import talib

plt.style.use('ggplot')
pd.options.display.max_rows = 20

df = pd.read_csv('DAT_ASCII_EURUSD_M1_2015.csv', sep=';',
                 names=('Time', 'Open', 'High', 'Low', 'Close', ''),
                 index_col='Time', parse_dates=True)
df.index += pd.offsets.Hour(7)

# cf. https://stackoverflow.com/a/36223274/8426544
# cf. http://nekopuni.holy.jp/2015/01/pythonnysol%E7%82%BA%E6%9B%BF%E9%AB%98%E9%A0%BB%E5%BA%A6%E3%83%87%E3%83%BC%E3%82%BF%E3%81%8B%E3%82%89%E4%BB%BB%E6%84%8F%E3%81%AE%E3%83%AD%E3%82%A6%E3%82%BD%E3%82%AF%E8%B6%B3%E3%83%81%E3%83%A3/
df = df.resample('1H').agg({
    'Open': 'first',
    'High': 'max',
    'Low': 'min',
    'Close': 'last',
}).ffill()
df['FastMA'] = talib.SMA(df['Close'].values, timeperiod=10)
df['SlowMA'] = talib.SMA(df['Close'].values, timeperiod=30)

df.plot(y=['Close', 'FastMA', 'SlowMA'])

from pandas_highcharts.display import display_charts
df = pd.DataFrame({'Close': df['Close'], 'FastMA': df['FastMA'], 'SlowMA': df['SlowMA']})
display_charts(df, chart_type="stock", title="MA cross", figsize=(640, 480), grid=True)

(参考)PythonでFXシストレのバックテスト(1)


resample() メソッドを使用することで時系列データの頻度を変換できます。日次のデータを週次や月次などのデータに変換できます。


どりらんさん共著の Jupyter 本に載ってる!(P.128 あたり)


Jupyter 上で動かせるチャートを書くなら、pandas-highcharts が良さげ。
python-highcharts もあるよ。