zaif（取引所）から情報を取得する

# zaif（取引所）からAPIを使って情報を取得する

* この記事はnode.jsのモジュールzaif.jpを使った記事になります
* public apiと呼ばれる認証のない情報取得だけのAPIを説明した記事になります
* monacoinなどの仮想通貨の取引所の記事になります

## 事前準備

モジュールをインストールします

```
npm install zaif.jp
```

## api使用例

promiseという手法でコールバックを管理しているので非同期のリクエストを簡単に扱うことが出来ます。
基本はthenとcatchだけ覚えておけば良いです。

* thenは正常処理
* catchはエラー処理

もっと細かい使い方や返ってくるデータを知りたければgithubに書いてあります
( https://github.com/you21979/node-zaif )

### 最新の価格を取得する

```
var api = require('zaif.jp').PublicApi;
var pair = 'mona_jpy';
api.lastPrice(pair).then(function(res){
    console.log(res)
})
```

### ティッカーを取得する

```
var api = require('zaif.jp').PublicApi;
var pair = 'mona_jpy';
api.ticker(pair).then(function(res){
    console.log(res)
})
```

### 板情報を取得する

```
var api = require('zaif.jp').PublicApi;
var pair = 'mona_jpy';
api.depth(pair).then(function(res){
    console.log(res)
})
```

### 歩み値を取得する

```
var api = require('zaif.jp').PublicApi;
var pair = 'mona_jpy';
api.trades(pair).then(function(res){
    console.log(res)
})
```

## 1秒に5回制限があるけど？

zaifは1秒に5回しか同一のIPから受け付けない制限があります。
これに一々エラー対応するのはめんどくさいので0.2秒に1回しかリクエスト出来ないように内部で実装されています。
（ http://qiita.com/you21979@github/items/7df609e33af5c7b7febb ）

ただし制限がありリクエスト情報をメモリ内に保持するので起動しっぱなしのサーバーでしか有効になりません。
起動しっぱなしにできないバッチ処理から使う場合にはローカルに以下のようなサーバーを立てることで回避できます。
(この方法だとPHPなど他の言語からでも使えます)

アクセスURL　http://localhost:8080/depth?pair=mona_jpy

```js:app.js
var api = require('zaif.jp').PublicApi;
var http = require('http');
var url = require('url');
http.createServer(function (request, response) {
    response.writeHead(200, {'Content-Type': 'text/html'});
    var urlinfo = url.parse( request.url , true );
    switch(urlinfo.pathname){
    case '/depth':
        if( 'pair' in urlinfo.query ){
            var f = function(count){
                if(count >= 5){
                    response.write(JSON.stringify({error:'error'}));
                    response.end();
                }else{
                    api.depth(urlinfo.query.pair.toLowerCase()).then(function(res){
                        response.write(JSON.stringify(res));
                        response.end();
                    }).catch(function(){
                        f(count+1);
                    })
                }
            }
            f(0);
        }
        break;
    case '/history':
        if( 'pair' in urlinfo.query ){
            var f = function(count){
                if(count >= 5){
                    response.write(JSON.stringify({error:'error'}));
                    response.end();
                }else{
                    api.trades(urlinfo.query.pair.toLowerCase()).then(function(res){
                        response.write(JSON.stringify(res));
                        response.end();
                    }).catch(function(){
                        f(count+1);
                    })
                }
            }
            f(0);
        }
        break;
    default:
        response.end();
        break;
    }
}).listen(8080);
```

※１　この方法でうまくいくのは普段は5秒に一回程度のリクエストしかないんだけど時々リクエストが重なるときの排他制御のみです。

## ストリームとして実装する

zaifはテスト運用だけどwebsocketに対応（以前からあったけど）したのでそちらを使えばマーケット情報の取得についてはほぼ制約がなくなる

ストリームに対応したライブラリも作ったので公開しておきます

### インストール

```
npm install zaif-market-stream
```

### サンプルサーバー

```js:app.js
var ZMS = require('zaif-market-stream');
var Promise = require('bluebird');
var http = require('http');
var url = require('url');
var ms = {
    mona_jpy: new ZMS.MarketStream('mona_jpy'),
    btc_jpy: new ZMS.MarketStream('btc_jpy'),
    mona_btc: new ZMS.MarketStream('mona_btc'),
};
Promise.all(Object.keys(ms).map(function(key){
    return ms[key].start()
})).then(function(){
    serverstart(ms);
})

var serverstart = function(ms){
    http.createServer(function (request, response) {
        response.writeHead(200, {'Content-Type': 'text/html'});
        var urlinfo = url.parse( request.url , true );
        switch(urlinfo.pathname){
        case '/depth':
            if( 'pair' in urlinfo.query ){
                response.write(JSON.stringify(ms[urlinfo.query.pair.toLowerCase()].depth()));
                response.end();
            }
            break;
        case '/lastupdate':
            if( 'pair' in urlinfo.query ){
                response.write(JSON.stringify(ms[urlinfo.query.pair.toLowerCase()].lastUpdate()));
                response.end();
            }
            break;
        case '/history':
            if( 'pair' in urlinfo.query ){
                response.write(JSON.stringify(ms[urlinfo.query.pair.toLowerCase()].trades()));
                response.end();
            }
            break;
        default:
            response.end();
            break;
        }
    }).listen(8080);
}
```

※ちなみにZMS.zaifと呼びだすとzaif.jpモジュールが呼べます

## サーバーとした場合の管理方法

foreverをインストールします。これはrootで行います

```
sudo npm install -g forever
```

サーバーを開始するとき

```
forever start app.js
```

サーバーを終了するとき

```
forever stop app.js
```