Python
システムトレード
Quantx

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

QuantXとは

QuantXとは,Pythonで投資アルゴリズムを開発出来るウェブアプリケーションです.
詳しくは,@hiroshimodaさんのPythonで投資アルゴリズムを開発してみるをご参照下さい.

シグナル関数の書き方

(ある程度,python と pandas と QuantXを知っている人向けに書いています.)

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

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

datapandas.Panel 型なのだから,このようにかけるはずだよね,と思ってSmartTradeさんに問い合わせたところ、dataはRead Onlyだそうで,itemを追加することは出来ないそうです.
よって下記のようには書けません:no_good_tone3:

## 間違った書き方!
    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)

ただしくは↓のように,変数に入れて扱わなくてはいけません.

    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使ってみる時は,こんな感じで書けばいいとおもいます.

    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)

注意点

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

提案

QuantXさん,
もし、functools の import が許されるなら、talib を使うアルゴリズムはこう書けるはずで、もっとすっきりするはずなのですが、いかがでしょうか?(自信ないけど.)

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アルゴリズム勉強会という会が開かれていて,QuantXの勉強をしたい人や,python でアルゴリズム書きたいとか,その他情報がほしい人などが集まっていますので,気になる方は参加してみてはいかがですか?

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