ブル・ベアファンド自動裁定 〜はじめの一歩〜

![115 [更新済み]-01.jpg](https://qiita-image-store.s3.amazonaws.com/0/318424/2ddff4af-d160-958b-bdc1-f2930bb9a7c3.jpeg)
# 導入
## お前だれ
都内某T大学部４年、機械学習・統計手法でバイオインフォマ、ケモインフォマでケモケモしたりFinTechしようとしている[株式会社Smart Trade](https://smarttrade.co.jp/)インターンの小林（[Twitterアカウント](https://twitter.com/Cat_to_Love))です。

[神田のランチリポーター](https://intern.quantx.io/archives/kanda_meshi)もやってます。

## 今回何やるの？
当社インターン５ヶ月目ということでいつまでも初心者とは言って居られなくなったので販売できそうなアルゴの実装を本気で目指して行きたいと思います。

その**"はじめの一歩"**として今回は以下を達成目標とします。

- ブル・ベアファンドの仕組みを理解する
- QuantX Factoryでブル・ベアファンドをの自動裁定を実装する

## QuantX Factoryって何？
株式会社Smart Tradeが

> " 金融の民主化 "

を理念に、これまで一部の有識者だけの物であったトレードアルゴリズムをより簡易にコード上で開発するためのプラットフォームです。
### 何が強いの？
- Web上のプラットフォームのため開発環境構築が不要であること
- 各銘柄の終値や高値などの各種データが用意されており<font color="Red">**データセットの用意不要**</font>  ([公式ドキュメント参考]
(https://determined-feynman-fb5a05.netlify.com/ja/dataset.jp.stock.html))
- 開発したトレードアルゴリズムは審査を通過すれば[QuantX Store](https://quantx.io/)で販売可能
- 上級者の方には[QuantX Lab](https://github.com/smartradev/quantx-lab)といった開発環境も

# 本題
## ブル・ベアファンドの仕組みを理解する
###ブル・ベアファンドとは
日経平均株価などの対応する株価指数の**短期**の値上がり・値下がりを利用して利益を出すことを狙いとした投資信託のことです。

上手くブル・ベアファンドの売買を行えば上昇相場でも下落相場でも利益を出すことができます。

ブル、ベアと二つの投資信託はそれぞれ対応する株価指数に対して特有の"動き方"と"倍率"を持っています。


### それぞれの動き方
まず、それぞれの**"動き方"**について見て行きましょう。

#### ブル型ファンド (Bull fund) の動き
<img width="1002" alt="スクリーンショット 2019-02-15 11.13.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/318424/d547e835-2b82-eb9f-9c37-8061542b431f.png">


その名からもわかる通り(レバレッジ型とも呼ばれます)
株価指数の<font color="Red">**値上がり**</font>に対し "牛の角が突き<font color="Red">**上げる**</font>" ように<font color="Red">**値上がり**</font>する投資信託のことで基本的には株価指数の値動きに対応するものと考えます。

上の図は黒線が対応する株価指数の動きであり<font color="Red">赤線</font>がブルファンドの値動きです。（イメージ）

この図からも

**"対応する株価指数が<font color="Red">上昇</font>する時はブルファンドを買う"**

という結論に至るかと思います。

#### ベア型ファンドの (Bear Fund) の動き
<img width="1001" alt="スクリーンショット 2019-02-15 11.14.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/318424/ac31336a-e21d-dd9d-3258-e8a63ea85d35.png">

これまたその名からわかる通り(インバース型とも呼ばれます)
株価指数の<font color="Red">**値上がり**</font>に対し "熊が爪を振り<font color="Blue">**下ろす**</font>" ように<font color="Blue">**値下がり**</font>する投資信託のことで基本的には株価指数の値動きに対して逆転するものと考えます。

上の図は黒線が対応する株価指数の動きであり<font color="Blue">青線</font>がベアファンドの値動きです。（イメージ）

この図からも

**"対応する株価指数が<font color="Blue">下落</font>する時はベアファンドを買う"**

という結論に至るかと思います。

### 倍率について
ブル・ベアファンドは対応する株価指標に対応して値動きすると説明しましたが、単純に等倍で値動きしている用では短期で大きな利益を出すことはできません。

そこで登場するのが値動きの倍率です。

少し例を見てみましょう

<table>
<tr style="background:#bcfa89">
  <th>銘柄コード</th>
  <th>銘柄名</th>
  <th>概要</th>
</tr>
<tr>
  <td>1367</td>
  <td>ダイワ上場投信　TOPIXレバレッジ</td>
  <td>TOPIXの動きの２倍の値動きをする</td>
</tr>
<tr>
  <td>1350</td>
  <td>日経平均レバレッジ・インデックス連動型上場投信</td>
  <td>日経平均の動きの２倍の値動きをする</td>
</tr>
<tr>
  <td>1356</td>
  <td>TOPIXベア2倍上場投信</td>
  <td>TOPIXの動きの２倍の逆転した値動きをする</td>
</tr>
<tr>
  <td>1357</td>
  <td>日経ダブルインバース上場投信</td>
　<td>日経平均の動きの２倍の逆転した値動きをする</td>
</tr>
</table>

大体２倍の銘柄が多いですがトリプルと言った３倍などもあります。
高い倍率のブルベアファンドのメリットとして短期の株価指数の少しの動きで大きな利益を得ることができることが挙げられますが、裏を返せば<font color="Red">**リスクも倍になるという事なので注意が必要です。**</font>

より詳細に値動きと損益に関して知りたいかたは[コチラ](https://www.toushikiso.com/column/bull_bear.html)をご覧ください。

## ブル・ベアファンドをの自動裁定を実装する
### 選択銘柄
- 1321 : 日経225連動型上場投資信託
    - これを今回のブルベアの対応する株価指標とします。
- 1570 : 日経平均レバレッジ上場投信 (ブル型)
- 1357 : 日経ダブルインバース上場投信 (ベア型)

以下各銘柄はそれぞれ株価指標・ブル・ベアと呼称します。

### 指標
今回は特に選定せず実装が容易い二つを選ぶました。
ここではブルベアの実装をメインとするので各指標の実装と理論についてはリンクの方を参照してください。
RCIに関してはインターン生の佐々木さん(@akihirosasaki)の実装を借りさせていただきました。

- RCI : (売られすぎ)-100 〜 100(買われすぎ)で判断。実装とその理論については[コチラ](https://qiita.com/akihirosasaki/items/f6aa808f49af20183bdb)
- RSI : (売られすぎ)0 〜 100(買われすぎ)で判断。実装とその理論については[コチラ](https://qiita.com/Ric418/items/81f6d5d7521305511e15)

### アルゴリズム
とりあえずははじめの一歩なのでアルゴリズムは単純にしました。

1. 上記の各指標を株価指標のみで計算し株価指標が上昇するか下落するかを予測
2. 予測結果の元
    1. 上昇する場合ブルを買い、ベアを売る
    2. 下落する場合ブルを売り、ベアを買う

### 実装
今回ははじめの一歩ですのでQuantX Factoryの使い方も含めて説明していきます、既に理解されている方は読み飛ばしつつでお願いします。

コードは[ここ](https://factory.quantx.io/developer/8c4bceb8d2cb44518ded9d55bd319a27)をスタートとして書いていきましょう。

![スクリーンショット 2019-02-15 13.33.02.png](https://qiita-image-store.s3.amazonaws.com/0/318424/763d31f5-9ac5-2be9-adb3-5b27d3bf16c4.png)

cloneボタンを押して好きな名前をつけてコピーを作成して下さい。

<details><summary>ここからも直接コピーできます</summary><div>

```py
#必要なライブラリの読み込み
import numpy as np
import pandas as pd
import talib as ta

#RCIを計算する関数
def get_rci(close, period):
      rank_period = np.arange(period, 0, -1)
      length = len(close)
      rci = np.zeros(length)
      for i in range(length):
          if i < period - 1:
              rci[i] = 0
          else :
              rank_price = close[i - period + 1: i + 1].rank(method='min', ascending = False).values
              rci[i] = (1 - (6 * sum((rank_period - rank_price)**2)) / (period**3 - period)) * 100
      return rci

def initialize(ctx):
    # 設定
    ctx.logger.debug("initialize() called")
    ctx.configure(
      channels={          # 利用チャンネル
        	"jp.stock": {
        		"columns": [
        		],
        		"symbols": [
        			
        		]
        	}
        
      }
    )

    def _my_signal(data):
      buy_sig = 
      sell_sig = 
      return {
        "buy:sig":buy_sig,
        "sell:sig":sell_sig,
      }

    # シグナル登録
    ctx.regist_signal("my_signal", _my_signal)

def handle_signals(ctx, date, current):
    '''
    current: pd.DataFrame
    '''
    
    # ctx.logger.debug(df)
    
    # ctx.logger.debug(df["buy:sig"])
    # ctx.logger.debug(df["sell:sig"])
    # 買いシグナル
   
    # 売りシグナル
    
```
</div></details>

#### 銘柄と終値などの読み込み
まずは今回使う銘柄と終値などのデータを読み込めるようにしましょう。

24行目から

```py
"jp.stock": {
        		"symbols": [
        			
        		],
        		"columns": [
        		  
        		]
        	}
```

の様なコードがあると思います、このコードを以下のコードにしましょう。(コピペを推奨します)

```py
"jp.stock": {
        		"symbols": [
        			"jp.stock.1321", #日経225連動型上場投資信託
        			"jp.stock.1357", #日経ダブルインバース上場投信 bear
        			"jp.stock.1570", #日経平均レバレッジ上場投信 bull
        		],
        		"columns": [
        		  "close_price_adj"
        		]
        	}
```

このコードは 
- `"jp.stock"` : 日本株
- `"symbols"` : 銘柄は指定した三つの銘柄コードのもの
- `"columns"` : 値は今回終値の調整値だけを用いるので `"close_price_adj"`
となります。

#### 指標の計算とシグナル出し
次はRCI、RSIを用いた指標計算に移ります。

38行目あたりの `def _my_signal(data)` から、ここは買い売りシグナル(今回は日経平均の上昇下落シグナル)を生成する部分となります。

```py
def _my_signal(data):
      buy_sig = 
      sell_sig = 
      return {
        "buy:sig":buy_sig,
        "sell:sig":sell_sig,
      }
```

このコードを以下の様に書き換えましょう

```py
def _my_signal(data):
      cp = data["close_price_adj"].fillna(method='ffill')
      # ctx.logger.debug(cp)
      rci9 = pd.DataFrame(0, index=cp.index, columns=cp.columns)
      rsi7 = pd.DataFrame(0,index=cp.index, columns=cp.columns)
      
      for (sym,val) in cp.items():
        rci9[sym]=get_rci(cp[sym], 9)
        
      for (sym,val) in cp.items():
        rsi7[sym] = ta.RSI(cp[sym].values.astype(np.double), timeperiod=7)
      # ctx.logger.debug(rci9)
      # ctx.logger.debug(rsi7)
      buy_sig= (rci9 < -80) | (rsi7 < 30)
      sell_sig= (rci9 > 80) | (rsi7 > 70)
      return {
        "buy:sig":buy_sig,
        "sell:sig":sell_sig,
        "rci9:g2":rci9,
        "rsi7:g2":rsi7,
      }
```

順を追って説明すると

```py
cp = data["close_price_adj"].fillna(method='ffill')
# データ"close_price_adj"の欠損を無くし使えるデータに整形
# ctx.logger.debug(cp) #データの中身が気になる方はこの行の先頭の#を外して実行してみて下さい。
rci9 = pd.DataFrame(0, index=cp.index, columns=cp.columns)
# 指標RCIの計算結果を保存するための容れ物を用意します、容れ物の形状はcpと同じにしています。
rsi7 = pd.DataFrame(0,index=cp.index, columns=cp.columns)
# 指標RSIの計算結果を保存するための容れ物を用意します、容れ物の形状はcpと同じにしています。
```

となり...

```py
for (sym,val) in cp.items():
  rci9[sym]=get_rci(cp[sym], 9)
for (sym,val) in cp.items():
  rsi7[sym] = ta.RSI(cp[sym].values.astype(np.double), timeperiod=7)
#指標RCI,RSIを計算する関数get_rci(),ta.RSI（）を呼び出し各銘柄においてfor分により計算しています。
# ctx.logger.debug(rci9)
# ctx.logger.debug(rsi7) #各指標RSI, RCIがどの様な値になっているか確認したい場合先頭の#を外して実行してみて下さい。
```

今回は株価指標の銘柄においてのみ格指標を計算すれば良いのですが今後拡張することを考え計算しておきます。ちなみにここではRCI, RSIそれぞれ9日、7日の期間で計算しています。

各指標の値で計算したのち...

```py
buy_sig= (rci9 < -80) | (rsi7 < 30)
# rci9が-80より小さい、もしくはrsi7が30より小さい時買いシグナルを出す(上昇すると予測)
sell_sig= (rci9 > 80) | (rsi7 > 70)
# rci9が80より大きい、もしくはrsi7が70より大きい時売りシグナルを出す(下落すると予測)
return {
  "buy:sig":buy_sig,
  "sell:sig":sell_sig,
  "rci9:g2":rci9,
  "rsi7:g2":rsi7,
}
#デバッグや結果に描画などでも使える様にreturnで返す
```

ここまでで株価指標の上昇と下落の予測シグナルを出すことができる様になりました。

ちなみに61行目の `ctx.regist_signal("my_signal", _my_signal)` でこのシグナルを登録しています。これをしなければ後で使えないのでしっかり登録しましょう。

#### シグナルの処理
ここからが本題です、63行目から `def handle_signals(ctx, date, current):` 以降を書いていきます。ここはデータ構造が少し複雑になるので順を追ってコードを書いていきます。

まず、

```py
'''
current: pd.DataFrame
'''
```


「 current: pd.DataFrame...？ 」

となる方もいるかと思いますので説明いたします、先ほども41行目あたりで出てきましたpd.DataFrameですがこれは**"容れ物"**です、が、ここの**"容れ物"**少し41行目のものとは訳が違います。

というと、この `current` という容れ物には既に中に色々入っています。
試しに `ctx.logger.debug(current)` を追加、以下のコードで実行し `current` 中身を確認しましょう。

```py
def handle_signals(ctx, date, current):
    '''
    current: pd.DataFrame
    '''
    ctx.logger.debug(current)
```

以下の様なログが出てきたと思います。

![スクリーンショット 2019-02-15 15.25.27.png](https://qiita-image-store.s3.amazonaws.com/0/318424/c00cec98-ea89-29eb-ca5c-30a5e140dc74.png)

ここでは上昇予測である<font color="Red">買いシグナル(buy:sig)</font>と下降予測である<font color="Blue">売りシグナル(sell:sig)</font>
を用いたいので `current["buy:sig"]` , `current["sell:sig"]`で指定します。

ただし今回は株価指標である`"jp.stock.1321"`の各シグナルのみ用いるので
`current["buy:sig"][0]`, `current["sell:sig"][0]`という指定になります。
ちなみにここでの `[0]` とは以下のDataFrameの0行目（株価指標のシグナル）を指定していることになります。

![スクリーンショット 2019-02-15 15.38.47.png](https://qiita-image-store.s3.amazonaws.com/0/318424/5daeba1e-37c1-133d-6602-f8eb3876fcd6.png)

これを踏まえてコードを以下の様に書きます。

```py
def handle_signals(ctx, date, current):
    '''
    current: pd.DataFrame
    '''
    # ctx.logger.debug(current)
    bear = ctx.getSecurity("jp.stock.1357")
    bull = ctx.getSecurity("jp.stock.1570")
    # 買いシグナル
    df_buy = current["buy:sig"][0]
    if df_buy:
      bull.order_target_percent(0.10, comment="BULL BUY")
      bear.order_target_percent(0, comment="BEAR SELL")
    # 売りシグナル
    df_sell = current["sell:sig"][0]
    if df_sell:
      bear.order_target_percent(0.10, comment="BEAR BUY")
      bull.order_target_percent(0, comment="BULL SELL")      
    
```

それぞれ説明すると、

```py
bear = ctx.getSecurity("jp.stock.1357")
#指定したベアの銘柄のオブジェクトをbearとして保存します、あとで注文に用います。
bull = ctx.getSecurity("jp.stock.1570")
#指定したブルの銘柄のオブジェクトをbullとして保存します、あとで注文に用います。
```

こうして取引する銘柄を指定した後

```py
# 買いシグナル
df_buy = current["buy:sig"][0]
if df_buy:
  bull.order_target_percent(0.10, comment="BULL BUY")
  bear.order_target_percent(0, comment="BEAR SELL")
```

- `df_sell`がTrueの時、つまりブルベアが対応する株式指標の銘柄が<font color="Red">値上がり</font>と予測
    - <font color="Red"> `bull` : **２倍値上がり**</font>するであろうブル銘柄の総保有額が総資産の10%となる様に買い
    - <font color="Blue"> `bear` : **２倍値下がり**</font>するであろうベア銘柄を総保有額が総資産の0%となる様に売る(全売り)

```py
# 売りシグナル
df_sell = current["sell:sig"][0]
if df_sell:
  bear.order_target_percent(0.10, comment="BEAR BUY")
  bull.order_target_percent(0, comment="BULL SELL")
```
- `df_buy`がTrueの時、つまりブルベアが対応する株式指標の銘柄が<font color="Blue">値下がり</font>と予測
    -  `bull` : <font color="Blue">**２倍値下がり**</font>するであろうブル銘柄を総保有額が総資産の0%となる様に売る(全売り)
    - `bear` : <font color="Red">**２倍値上がり**</font>するであろうベア銘柄の総保有額が総資産の10%となる様に買い

そのほかの注文方法は[公式ドキュメント参考にしてください](https://determined-feynman-fb5a05.netlify.com/ja/api.html#Security)

やっと完成です！
一応完成コードは[コチラ](https://factory.quantx.io/developer/0c42e5884489491d8cad673c95d0b9fd)

## 結果
![スクリーンショット 2019-02-15 16.19.42.png](https://qiita-image-store.s3.amazonaws.com/0/318424/fe65df95-93c6-be79-5c19-528466a4f86e.png)


### 評価・考察
- 結果からわかる様に下落が連続的に続く場面に関して一定の利益を上げている
- 日経平均が細かく上下を繰り返すと振り回されて損失を出すことが多くなる
- 各種指標RSI・RCIの計算期間が短すぎると日経平均に過敏に反応してしまう？

### 今後の展望
- ブルベアの特徴である短期トレードに強い指標を選別する。
- 利確・損切り機能をつけて安定性をつける。

##終わりに
今回は販売可能なレベルを目指しブルベアアルゴリズムの実装を目指しました。
今後開発の進捗を報告する予定ですのでよろしくお願いいたします。

##宣伝

###もくもく会もやってるよ
**日時**：毎週水曜日18時〜
**場所**：神田　千代田共同ビル４階　SmartTrade社オフィス
**内容**：基本黙々と自習しながら猛者の方に質問して強くなっていく会
**備考**：お菓子と終わりにお酒が出るよ

###詳細はこちらだよ
Pythonアルゴリズム勉強会HP：[https://python-algo.connpass.com/](https://python-algo.connpass.com/)
(connpassって言うイベントサイトに飛びます)

##免責注意事項
このコード・知識を使った実際の取引で生じた損益に関しては一切の責任を負いかねますので御了承下さい。

## materials
bull-bear:<a href='https://jp.freepik.com/free-vector/ベクター画像_2461918.htm'>Designed by Rawpixel.com</a>