QuantXで初めてのアルゴリズムを書いてみて気づいたことをちょっと．

# QuantXとは

QuantXとは，Pythonで投資アルゴリズムを開発出来るウェブアプリケーションです．
詳しくは，[@hiroshimoda](https://qiita.com/hiroshimoda)さんの[Pythonで投資アルゴリズムを開発してみる](https://qiita.com/hiroshimoda/items/e89444729fe7d25c0275)をご参照下さい．

# シグナル関数の書き方
（ある程度，python と pandas と QuantXを知っている人向けに書いています．)


QuantXの株価情報は `pandas.Panel` に入っていて，パネル使いにとっては便利な構造です．

Panel に慣れている人であれば， QuantX の help に記載されている
[[DEMO] 移動平均を使った基本的なアルゴリズム](https://quantx.io/demo/81dd0231dda83b4ac461b99fbdb6a4bf95756df4c05447552c7b3434b583c2b3)も，このように書き直したくなるとおもいますが，

**`data` は `pandas.Panel` 型なのだから，このようにかけるはずだよね，**と思ってSmartTradeさんに問い合わせたところ、**<font color="#FF0000">dataはRead Onlyだそうで，itemを追加することは出来ないそうです．</font>**
よって下記のようには書けません:no_good_tone3:


```python
## 間違った書き方！
    def _mavg_signal(data):

      ##欠損値を埋める
      data["close_price_adj"] = data["close_price_adj"].fillna(method='ffill')
      data["ma25"] = data["close_price_adj"].rolling(window=25, center=False).mean()
      data["ma75"] = data["close_price_adj"].rolling(window=75, center=False).mean()
      data["ratio"] = data["ma25"] / data["ma75"] 
      data["buy_signal"] = (data["ratio"] > 1.02) & (data["ratio"] < 1.05)
      data["sell_signal"] = data["ratio"] < 0.95
      
      return {
        "MA_25": data["ma25"], 
        "MA_75": data["ma75"], 
        "buy:sig": data["buy_signal"],
        "sell:sig": data["sell_signal"],
      }
      
    ctx.regist_signal("_mavg_signal", _mavg_signal)
      
```
ただしくは↓のように，変数に入れて扱わなくてはいけません．

```python

    def _mavg_signal(data):

      ##欠損値を埋める
      data["close_price_adj"] = data["close_price_adj"].fillna(method='ffill')
      ma_25 = data["close_price_adj"].rolling(window=25, center=False).mean()
      ma_75 = data["close_price_adj"].rolling(window=75, center=False).mean()
      ratio = ma_25 / ma_75

      buy_signal = (ratio > 1.02) & (ratio < 1.05)
      sell_signal = ratio < 0.95
      
      return {
        "MA_25": ma_25, 
        "MA_75": ma_75,
        "buy:sig": buy_signal,
        "sell:sig": sell_signal,
      }
      
    ctx.regist_signal("_mavg_signal", _mavg_signal)
```

[ta-lib](https://github.com/mrjbq7/ta-lib)使ってみる時は，こんな感じで書けばいいとおもいます．

```python
    def _wma_signal(data):
      TIME_PERIOD = 25
      data["close_price_adj"] = data["close_price_adj"].fillna(method='ffill')

      dwna = dict()
      dwna_roc = dict()
      for symbol in data.minor_axis:
        dwna[symbol] = ta.WMA(data["close_price_adj"][symbol].values.astype(np.double), timeperiod=TIME_PERIOD)
        dwna_roc[symbol] = ta.ROC(dwna[symbol], 1) 
      
      wma = pd.DataFrame(dwna, index=data.major_axis)
      wma_roc = pd.DataFrame(dwna_roc, index=data.major_axis) 

      buy_sig = wma_roc > 0
      sell_sig = wma_roc< 0
      ctx.logger.info(buy_sig)      
      
      return {
        "wma_25":wma,
        "wma_roc_25": wma_roc,
        "buy:sig":buy_sig,
        "sell:sig": sell_sig,
      }
      
    # シグナル登録
    ctx.regist_signal("wma_signal", _wma_signal)

```
<!-- 以前の間違った書き方を残しておきます．

```python
    def _wma_signal(data):
      
      TIME_PERIOD = 25
      data["close_price_adj"] = data["close_price_adj"].fillna(method='ffill')
      dwna = dict()
      dwna_roc = dict()
      for symbol in data.minor_axis:
        dwna[symbol] = ta.WMA(data["close_price_adj"][symbol].values.astype(np.double), timeperiod=TIME_PERIOD)
        dwna_roc[symbol] = ta.ROC(dwna[symbol], 1) 
      
      data["wma"] = pd.DataFrame(dwna)
      data["wma_roc"] = pd.DataFrame(dwna_roc)
      data["buy_sig"] = data["wma_roc"] > 0
      data["sell_sig"] = data["wma_roc"] < 0

      return {
        "wma_25":data["wma"],
        "wma_roc_25": data["wma_roc"] ,
        "buy:sig":data["buy_sig"],
        "sell:sig": data["sell_sig"],
      }

    ctx.regist_signal("_wma_signal", _wma_signal)
```

-->



### 注意点
1. `return` に渡す辞書の key 名は，dataの item 名と**被ってはいけません**．例えば `"ma25": data["ma25"]`と渡すと，`ValueError columns overlap but no suffix specified ` と怒られます．
2. ~~保存ボタンを押さないと，保存されません:sob:．他のページに（誤って）移動してしまった場合でも，警告も出ません
:scream:．お気をつけ下さい．~~ ←これは警告が出るように修正されました！


## 提案
QuantXさん，
もし、functools の import が許されるなら、talib を使うアルゴリズムはこう書ける**はず**で、もっとすっきりするはずなのですが、いかがでしょうか？（自信ないけど．）

```python

import functools

    def _wma_signal(data):
      
      TIME_PERIOD = 25
      mywma = functools.partial(ta.WMA,timeperiod=TIME_PERIOD)
      myroc = functools.partial(ta.ROC, timeperiod=1)

      data["close_price_adj"] = data["close_price_adj"].fillna(method='ffill')
      wma = data["close_price_adj"].apply(mywma)
      wma_roc = data["close_price_adj"].apply(myroc)
      buy_sig= wma > 0
      sell_sig = wma_roc < 0

      return {
        "wma_25":wma,
        "wma_roc_25": wma_roc,
        "buy:sig":buy_sig,
        "sell:sig": sell_sig,
      }
      
    # シグナル登録
    ctx.regist_signal("_wma_signal", _wma_signal)
    
    

```
# 勉強会

ほぼ，毎週水曜日，SmartTradeさんの会議室で，[Pythonアルゴリズム勉強会](https://python-algo.connpass.com/)という会が開かれていて，QuantXの勉強をしたい人や，python でアルゴリズム書きたいとか，その他情報がほしい人などが集まっていますので，気になる方は参加してみてはいかがですか？

私は，だいたい毎回行っています:grinning: