MACDのアルゴリズム #QuantX

## MACD 

MACD とは，期間の長い[指数移動平均](https://ja.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87#%E6%8C%87%E6%95%B0%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87)と短い指数移動平均の差を使って売買シグナルを出す指標です．


![](https://www.nomura.co.jp/learn/chart/images/chart_08_img04_2.gif) 
(出典：[野村證券 | 株・FXに今すぐ活かせる チャートの読み方・使い方 - トレンドフォロー系指標「移動平均」と「MACD」](https://www.nomura.co.jp/learn/chart/page8.html))


計算式はこのようになります．

```

MACD = SlowEMA - FastEMA
MACDSignal = SMA(MACD) 

ただし
　SlowEMA : 期間の長い指数移動平均
　FastEMA : 期間の短い指数移動平均
　SMA：移動平均関数

``` 

## シグナル

上記の図の通り，MACDがMACDSignalを上抜いた時，ロングポジションを取ります．

## 手仕舞い

利益確定水準+5.0％
損切り水準　-3.0％


## コード

```python
import pandas as pd
import talib as ta
import numpy as np


def initialize(ctx):
    # 設定
    ctx.fastperiod = 12 
    ctx.slowperiod = 26 
    ctx.signalperiod = 9 
    ctx.target = 0.10 
    ctx.plofit = 0.05 
    ctx.losscut = -0.03 
    
    ctx.codes = [6758, 8316, 2914, 7267, 7182, 8058, 8411, 4063, 7751, 5411,
                6981, 6902, 3382, 8766, 6367, 6752, 4911, 8001, 6301, 6503, 
                8031, 5108, 4519, 4578, 1925, 2502, 8801, 2503, 8750, 6273, 
                7741, 7270, 6971, 4901, 8053, 6869, 6502, 8113, 8725, 8267, 
                9843, 1605, 4612, 6702, 9021, 8308, 7309, 4188, 6762, 4528, 
                9202, 2413, 7181, 3402, 6586, 3092, 1878, 6988, 1801, 9502]

    ctx.symbol_list  = ["jp.stock.{}".format(code) for code in ctx.codes[:50]]
    ctx.configure(
      channels={          # 利用チャンネル
        "jp.stock": {
          "symbols": ctx.symbol_list,
          "columns": ["close_price_adj"],    # 終値(株式分割調整後) 
          }})

    def _MACD_SIGN(data):
      
      df_close = data["close_price_adj"].fillna(method='ffill')
      
      d_macd = dict() 
      d_macdsignal = dict()
      d_macdhist = dict() 
      
      # memo参照
      for symbol in data.minor_axis:
        macd, macdsignal, macdhist = ta.MACD(df_close[symbol].values.astype(np.double), 
                                          fastperiod=ctx.fastperiod , slowperiod=ctx.slowperiod, signalperiod=ctx.signalperiod)
        d_macd[symbol] = macd
        d_macdsignal[symbol] = macdsignal
        d_macdhist[symbol] = macdhist
                
      df_macd = pd.DataFrame(d_macd, index=data.major_axis)        
      df_macdsignal = pd.DataFrame(d_macdsignal, index=data.major_axis)        
      df_macdhist = pd.DataFrame(d_macdhist, index=data.major_axis)
      
      buy_sig = (df_macd > df_macdsignal) &  (df_macd.shift(1) < df_macdsignal.shift(1))


      return {
          "MACD": df_macd, 
          "MACDSignal": df_macdsignal, 
          "MACDHist": df_macdhist, 
          "buy:sig": buy_sig, 
        }

    # シグナル登録
    ctx.regist_signal("MACD_SIGN", _MACD_SIGN)

def handle_signals(ctx, date, current):

    df = current.copy()

    # 買いシグナル
    df_long = df[df["buy:sig"]]
    if not df_long.empty:
      for (sym, val) in df_long.iterrows(): 
        #ctx.logger.info(val)
        sec = ctx.getSecurity(sym)
        msg = "買いシグナル"
        sec.order_target_percent(ctx.target, comment= msg)

    # ポジションクローズ
    for (sym,val) in ctx.portfolio.positions.items():
        returns = val["returns"]
        
        if returns < ctx.losscut:
          sec = ctx.getSecurity(sym)
          sec.order_target_percent(0, comment= "損切り")
        elif returns > ctx.plofit:
          sec = ctx.getSecurity(sym)
          sec.order_target_percent(0, comment= "利益確定売")

```

## メモ

#### TA-lib　
[TA-Lib](https://mrjbq7.github.io/ta-lib/func_groups/momentum_indicators.html)は，テクニカル分析の主な指標を算出してくれるライブラリです．色々な指標計算関数が用意されているので便利なのですが，Documentがいまいちで，この返り値は一体なんなの？ということが良くあります．
macd は以下の関数を使います．

```macd, macdsignal, macdhist = MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)```

####  `data.minor_axis` 

`data` は，プロジェクトに最初から用意されているオブジェクトで，指定した銘柄の株価データを `pd.Panel` の形で保持しています．
（詳しくは，公式ドキュメントの[売買シグナル生成部分](https://factory.quantx.io/handbook/ja/#signal-emitter)にある `data` の説明を参照して下さい．）

`data.minor_axis` で，銘柄オブジェクトのリストを取得できますので，これをループに渡します．ループでは， `df_close` のコラム名として銘柄オブジェクト渡して，各銘柄の `pd.Serise` データを取得し，これを `.values.astype(np.double)` で ta-lib が引き取る事ができる `array` 型に変えて，`macd` に渡します．
先に用意しておいた辞書オブジェクト(`d_macd`など)に追加し，ループ終了後に辞書オブジェクトを 'pd.DataFrame' 型のデータに変えています．
そうすることで， `buy_sig` を簡単に作成することができます．

## 結果

![2018-07-31_17.jpg](https://qiita-image-store.s3.amazonaws.com/0/14019/f13300a9-7f98-baf1-ccf2-e1f901be5153.jpeg)


## 感想

+ 7月が終わりますね・・・
+ 長期，短期，およびMACDの移動平均の期間の長さは， `macd` でデフォルトで使われていた期間を使用しました．
+ 今回の銘柄も東証一部上場銘柄を適当に拾ってきました．



## 免責注意事項
+ このコードに基づき投資した結果、損害が発生しても，一切責任を持ちません．
+ このコードが正しく機能する保証は一切致しません．
+ このアルゴリズムを勧めているわけではありません．あくまで QuantX / Python のサンプルコードとして掲載しているだけです．