QuantXでCHO（チャイキンオシレータ）の実装　#QuantX

#今回やったこと
A/Dという金融指標を用いて、CHOというオシレータ指標を弄ってみました。

##CHOとは?
CHO(チャイキンオシレータ)とはFX取引で有名なプラットフォームであるMT4の後継に当たるMT5から導入された指標になります。基本的には名前の通りオシレーター系の指標で出来高と価格(終値、安値、高値)の関係から相場の売られすぎ、買われすぎを判断する指標になります。出来高を使っているのがCHOの特徴です。

CHOはA/Dという金融指標のMACDに相当します。

##A/Dとは？
A/DとはAccumulation(集積)/Distribution(離散)の略で
「集積」とは、価格の上昇として現れない買い勢力の増加です。
「離散」とは、価格の下落を伴わない、売り勢力の増加です。
集積や離散はテクニカル指標で価格を伴わないので見てもわかりません。
そこで出来高は価格に先行するという傾向を利用して、価格分析に出来高分析を加えたものがA/Dになります。

計算式は

```math
A/D = \frac{(C-L)-(H-C)}{H-L}\times V
```

C:当日終値　L:当日安値　H:当日高値　V:当日出来高

となります。

##CHOの計算式
CHOの計算式は３日指数平滑移動時平均から10日指数平滑移動時平均を引き算したものになります。

```
CHO = EMA(A/D,3) - EMA(A/D,10)
```

今回はTA-LIbでA/Dを出した後そのパラメータをEMAで計算してCHOを出します。


##CHOの売買シグナル

**買いシグナル**
ゼロラインを下から上に突き抜ける
**売りシグナル**
ゼロラインを上から下に突き抜ける

今回はこのようにシグナルを出していきます。

本来は他の指標と組み合わせて使うのがベストですが、可視化しやすいようにCHO単体でシグナルを出していきます。

##コード
公開アルゴリズムは以下のリンクから
https://factory.quantx.io/developer/6b8f7e6076b6426e8d234703ff6b624f

```python:cho.py
import talib as ta 
import pandas as pd 
import numpy as np 

#関数の初期化
def initialize(ctx):
  #設定
    ctx.logger.debug("initialize() called")
    ctx.configure(
      target="jp.stock.daily",
      channels={          #銘柄選択
        "jp.stock": {
          "symbols": [
            "jp.stock.2317", 
            "jp.stock.3150", 
            "jp.stock.3665", 
            "jp.stock.3687",
            "jp.stock.3836", 
            "jp.stock.3923", 
            "jp.stock.3962",
            "jp.stock.6035",
            "jp.stock.6046", 
            "jp.stock.6050",
            "jp.stock.6055", 
            "jp.stock.6067",
            "jp.stock.6200", 
            # "jp.stock.6920",
          ],
          "columns": [
            "high_price_adj",     # 高値(株式分割調整後)
            "low_price_adj",      # 安値(株式分割調整後)
            "close_price_adj",    # 終値(株式分割調整後) 
            "volume_adj",    # 取引高(株式分割調整後) 
          ] 
        }
      }
    )

    #シグナル定義
    def _mysignal(data):
      #各銘柄の終値(株式分割調整後)を取得、欠損データの補完 
      hp = data["high_price_adj"].fillna(method='ffill')
      lp = data["low_price_adj"].fillna(method='ffill')
      cp = data["close_price_adj"].fillna(method='ffill')
      vp = data["volume_adj"].fillna(method='ffill')

      #データの入れ物を用意
      AD = pd.DataFrame(data=0,columns=[], index=cp.index)
      EMA_3 = pd.DataFrame(data=0,columns=[], index=cp.index)
      EMA_10 = pd.DataFrame(data=0,columns=[], index=cp.index)
      CHO = pd.DataFrame(data=0,columns=[], index=cp.index)
      
      #TA-Libによる計算
      for (sym,val) in cp.items():
        AD[sym] = ta.AD(hp[sym].values.astype(np.double), 
                                lp[sym].values.astype(np.double), 
                                cp[sym].values.astype(np.double),
                                vp[sym].values.astype(np.double),)
        EMA_3[sym] = ta.EMA(AD[sym].values.astype(np.double),timeperiod=3)
        EMA_10[sym] = ta.EMA(AD[sym].values.astype(np.double),timeperiod=10)
      
      CHO = EMA_3 - EMA_10
      
      #売買シグナル
      buy_sig = CHO[(CHO > 0 ) & (CHO.shift(1) < 0)]
      sell_sig = CHO[(CHO < 0 ) & (CHO.shift(1) > 0)]
      # ctx.logger.debug(buy_sig)
      
      return {
        "AD": AD,
        "CHO:g2":CHO, 
        "buy:sig":buy_sig,
        "sell:sig":sell_sig,    
        }

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

def handle_signals(ctx, date, current):
    df = current.copy()

    done_syms = set([])
    # for (sym,val) in ctx.portfolio.positions.items():
    #     returns = val["returns"]
    #     if returns < -0.03:
    #       sec = ctx.getSecurity(sym)
    #       sec.order(-val["amount"], comment="損切り(%f)" % returns)
    #       done_syms.add(sym)
    #     elif returns > 0.05:
    #       sec = ctx.getSecurity(sym)
    #       sec.order(-val["amount"], comment="利益確定売(%f)" % returns)
    #       done_syms.add(sym)

    
    buy = current["buy:sig"].dropna()
    for (sym,val) in buy.items():
        if sym in done_syms:
          continue
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0.10, comment = "買いシグナル")
        # ctx.logger.debug("BUY: %s,  %f" % (sec.code(), val))
        pass

    sell = current["sell:sig"].dropna()
    for (sym,val) in sell.items():
        if sym in done_syms:
          continue
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment = "売りシグナル")
        # sctx.logger.debug("SELL: %s,  %f" % (sec.code(), val))
        pass
      
```

銘柄は成績が良かったもの
手仕舞いはシグナルのみで行なっています。

##バックテスト結果
<img width="808" alt="スクリーンショット 2019-02-01 17.07.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/318447/7ed3e575-e48e-3e5f-78c5-95e6c0086146.png">

他の指標と比較するとそんなに成績がよくないかもしれません。

##終わりに
今回はTA-Libで計算したものをさらにTA-Libで計算しました。
このような指標はたくさんあるのでその際参考にしていただければいいかなと思います。

##金融用語まとめ
バックテスト後の上にある金融指標が損益率意外よくわからないなあという方向けです。

[ドローダウン](https://www.nomura.co.jp/terms/japan/to/A01914.html)
[ボラティリティ](https://www.nomura.co.jp/terms/japan/ho/volatility.html)
[アルファ](https://www.nomura.co.jp/terms/japan/a/alpha.html)
[ベータ](https://www.nomura.co.jp/terms/japan/he/beta.html)

##予告
2/16日に大学生向けのイベントを開きます。
http://algorithms-contest.quantx.io/

##宣伝
勉強会やってます！
日時：毎週金曜日19時〜
場所：神田　千代田共同ビル４階　SmartTrade社オフィス
内容：初心者(プログラミングってものを知らなくてもOK)向けに初心者(私とか)がこんな内容をハンズオン(一緒にやる事)で解説しています
備考：猛者の方も是非御鞭撻にいらして下さい、そして開発・伝導者になりましょう！

もくもく会もやってます！
日時：毎週水曜日18時〜
場所：神田　千代田共同ビル４階　SmartTrade社オフィス
内容：基本黙々と自習しながら猛者の方に質問して強くなっていく会
備考：お菓子と終わりにお酒を飲みながら参加者と歓談できます！

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

インターンブログも書いてます！！
インターン活動期や神田メシ（？）なども書いたりしてます！
興味あれば是非みてください！！
http://intern.quantx.io/


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