よつぴいてひやふつと射る

化学メーカー勤務の弱小技術職がチラシの裏風に雑然と書いていきます

SQLAlchemyでローカルに保存したSQLite3のdbファイルにパスを通す

ちょっと悩んだので張っときますね。
ちなみにWindows環境です。

sqlite:///C:\\path\\to\\database.db
from sqlalchemy import create_engine
engine = create_engine("sqlite:///D:\\foo\\bar.sqlite3", echo=True)

python - SQLAlchemy engine absolute path URL in windows - Stack Overflow

スラッシュ4つ説とか出てきたけど3つでいけるみたい。
この手のって、ググると何かしら引っかかってくるんだけど、Linux前提の記事が多いんだよね…

ちなみにこのURLの書き方はRFC-1738というらしい。
ちょっと調べると沼が深そうだったので逃げます。
データベースエンジン — SQLAlchemy 0.6.5 ドキュメント (和訳)

Bitcoinの自動取引システムっぽいものを作る1

今更ながら、Bitcoinで金儲けをしたいという邪な欲望が芽生えてきました。
早速口座をいくつか開設して、ぽちぽちしてみたところ、ランダムに増えたり減ったりするだけだったので自動取引っぽいものを作りたいな、作れたらな、という記事です。
この分野には先人が何人もいてブログ記事もたくさんあるのでそれらを参考にして作るn番煎じです。

何はともあれ価格の時系列取得

使ったもの

bitFlyer LightningのAPIをPythonから使えるパッケージ「pybitflyer」を作りました - おおかみ山

とりあえず、1分足の取得場所が探した限りはなかったので、ティック情報を取得することに。
BitflyerのAPIは、マニュアルを見たけど何言ってるか理解できなかったので、先人のライブラリを使わせていただきました。感謝。
下のブログの記事も見ながらライブラリのコードも見ながら勉強中です。
11月, 2017 | いろいろてすと中

import pybitflyer
import json
import sqlite3
import time
from logging import getLogger, StreamHandler, FileHandler, DEBUG, INFO

logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(INFO)
handler_f = FileHandler(filename='logger.log')
handler_f.setLevel(INFO)
logger.addHandler(handler)
logger.addHandler(handler_f)


class BTFlyer():
    def __init__(self):
        self._api = pybitflyer.API(api_key='キー',
                                   api_secret='シークレット')
        self._conn = sqlite3.connect('D:\\BTdata\\bitflyer\\ticker.db')
        self._cur = self._conn.cursor()

    def close(self):
        self._cur.close()
        self._conn.close()

    def get_ticker(self, inst):
        print('getting ticker data:' + inst)
        table_name = 'tick_data_' + inst
        sql = '''CREATE TABLE IF NOT EXISTS ''' + table_name + ''' (
        best_ask real,
        best_ask_size real,
        best_bid real,
        best_bid_size real,
        ltp real,
        product_code text,
        tick_id int,
        timestamp text,
        total_ask_depth real,
        total_bid_depth real,
        volume real,
        volume_by_product real,
        PRIMARY KEY(tick_id)
        )'''  
        self._cur.execute(sql)

        while True:
            try:
                data = json.dumps(self._api.ticker(product_code=inst))
            except Exception as e:
                print(e)
                logger.info(e)

            data_dict = json.loads(data)
            tuple_of_ticker_data = (
                data_dict['best_ask'],
                data_dict['best_ask_size'],
                data_dict['best_bid'],
                data_dict['best_bid_size'],
                data_dict['ltp'],
                data_dict['product_code'],
                data_dict['tick_id'],
                data_dict['timestamp'],
                data_dict['total_ask_depth'],
                data_dict['total_bid_depth'],
                data_dict['volume'],
                data_dict['volume_by_product'])
            sql = '''REPLACE INTO ''' + table_name + '''
                    ('best_ask',
                     'best_ask_size',
                      'best_bid',
                      'best_bid_size',
                      'ltp',
                      'product_code',
                      'tick_id',
                      'timestamp',
                       'total_ask_depth',
                       'total_bid_depth',
                       'volume',
                       'volume_by_product')
                    VALUES(?,?,?,?,?,?,?,?,?,?,?,?)'''
            self._cur.execute(sql, tuple_of_ticker_data)
            print('got ticker on {0} bid {1}, ask {2}'.format(data_dict['timestamp'],
                                                              data_dict['best_bid'],
                                                              data_dict['best_ask']))
            self._conn.commit()
            time.sleep(1)  # アクセス規制 に引っかからないように


if __name__ == '__main__':
    try:
        btf = BTFlyer()
        btf.get_ticker('FX_BTC_JPY')
    except:
        btf.close()

これで1秒ごとにSQLiteにティック情報が書き込まれるので、後はそれを読むだけ。

問題は板情報をどうするか…
SQLiteには多分入らないよね…

bokeh.charts has been removed

最近、jupyter notebook使ってグラフ書くなら、bokehとかplotlyとか、matplotlib以外にもいろいろあるって知ってさっそく試そうとしてたんですよ。
bokehってのがよさげだったので、早速時系列データ表示するサンプルコード書いたら、jupyter先生にモジュールが無いって怒られまして、20分ほどかかってたどり着いたのが下記の公式ページ

bokeh.pydata.org

Deprecated bokeh.charts support removed

最新版 0.12.9 から削除されたらしいです。

これからbokeh触ってみる人は注意。

20分を無駄にした怒りとともに。

QNAP NASでcrontabを設定する

時々、何かの拍子でcrontabが働かなくなっているので、再設定のための備忘録としてメモ。
いわゆる、NASを再起動しても消えないタイプのcrontab設定法です。

現設定の確認

 crontab -l

設定ファイルの書き換え

 vim /etc/config/crontab
 で設定ファイルを開いて、
 30 15 * * * python /share/CACHEDEV1_DATA/.../hoge.py >> log.log
 とかを設定。

設定を反映して再起動

 crontab /etc/config/crontab
 /etc/init.d/crond.sh restart

QNAPのNASにPython/lxml環境を構築する

NAS: TS-231

Python:2 or 3

lxml: 3.7.3

 

numpy/pandasを入れてからしばらく経ちましたが、仕事が忙しくて疲れていたと言い訳をまず書いておきます。

さて、pythonでのスクレイピングに必要になってくるlxmlパッケージをインストールするところでまた躓いたのでメモしておきます。

python2でも3でも、SSH接続して単純に"pip install lxml"するだけではエラーが出るので、"opkg install libxml2 libxslt"などで関連ライブラリをインストールします。

ただし、それでも以下のようなエラーが出ます。

 

src/lxml/includes/etree_defs.h:14:31: fatal error: libxml/xmlversion.h: No such file or directory
 #include "libxml/xmlversion.h"
                               ^
compilation terminated.
Compile failed: command 'arm-openwrt-linux-gnueabi-gcc' failed with exit status 1
cc -I/usr/include/libxml2 -c /opt/tmp/xmlXPathInitg7GyME.c -o opt/tmp/xmlXPathInitg7GyME.o
unable to execute 'cc': No such file or directory
*********************************************************************************
Could not find function xmlCheckVersion in library libxml2. Is libxml2 installed?
*********************************************************************************
error: command 'arm-openwrt-linux-gnueabi-gcc' failed with exit status 1'''

 

試しにxmlversion.hを検索してみると、

# find / -name "xmlversion.h"
/share/CACHEDEV1_DATA/.qpkg/Entware-ng/include/libxml2/libxml/xmlversion.h

 

パスが通ってないっぽいのでしばらくググってみると

Package Request: python27-lxml · Issue #201 · Entware-ng/Entware-ng · GitHub

ここの回答の通り、シンボリックリンクを張ることで解決しました。

ln -s /opt/include/libxml2/libxml/ /opt/include/libxml

QNAPのNASにPython3/numpy/pandas環境を構築する

この手の情報は、あまりNAS の使用者が多くないのか、Pythonなんて入れる人いないのか、日本語の情報はもとより、英語の情報も非常に数が少なかったので備忘録兼情報公開の意味で投稿します。最初はssh? ARM? Linuxのコマンドはcdとlsしか知らない程度の知識だったため、トータル1週間くらい悩んでました…

 

QNAP製のNAS  TS231+での環境構築です。

Python機械学習使っていろいろ遊びたいんですが、ある種のデータは日々更新されて過去ログが公開されないため、毎日忘れずにダウンロードする必要があります。

それを自動実行するために一日中起動しているNASを使おうと思い立ったわけです。

Pandasやnumpy使わなくてもできるんですが、使えたほうが楽なので…

 

1.NASssh接続できるようにする

 手元のPCにTeraTermを入れ、NASにadminでログイン。以下sshでの操作。

 

2.NASにEntware-ngを入れる

 ググるとipkgやqpkgやEntwareなどが出てくるが、今使えるのはEntware-ngらしい。

 公式サイトに書いているコマンドでセットアップする。

 

3.gccを入れる

 opkg list update

 opkg install gcc

 他にも何か入れたかもしれないが忘れた。

 

4.python3を入れる。

 うちの環境はデフォルトでpython2系が入っていたが、せっかくなので3系を入れておく。

opkg install python3

 ちなみに、

opkg list | grep python*

 で表示されるpython関係のパッケージのいくつかは、opkgからインストールできた。

 このタイミングでpip3もインストールした。

 

5.arm-openwrt-linux-gnueabi-gcc-arのシンボリックリンクを作成。

  この状態で pip3 install numpyしてもCコンパイル時にエラーが出てしまう。

 arm-openwrt-linux-gnueabi-gcc-ar コマンドが not found といわれたので、私の環境では \opt\lib\ にあった ar に対してシンボリックリンクを作成した。

 windowsしか使ったことない人間にとっては難易度高かった・・・

 

6.pip3 install numpy pandas 

 

以上でした。

次はcronの設定するぞ。

pandas のread_csvを使って日本語入りのcsvを読み取る際の注意点

pandasはcsvを扱うための便利なメソッドが用意されていますが、日本語の入ったcsvファイルの読み込みにちょっと躓いたので個人的備忘録。

読み込み:

import pandas as pd
df=pd.read_csv('hoge.csv',encoding='Shift_JIS', index_col =0)

pd.to_csv()で普通にDataFrameをcsvに書き込むと、先頭列にインデックスがカラム名なしで書き込まれ、エンコードの問題も発生しました。