Help us understand the problem. What is going on with this article?

新高値更新のアルゴリズム #QuantX

More than 1 year has passed since last update.

新高値更新

ある株の銘柄の本日の高値が、過去の一定期間における最高値を更新した場合、相場の一段高を暗示し、買いシグナルになるそうです.これを新高値更新と呼ぶそうです。
今回は、これを使ってQuantXでシミュレーションをしてみます。

シグナル

ここでは本日の高値と過去10日間の最高値を見て、新高値更新の判定をし、取引シグナルとすることにします.株価の比較には、株式分割調整後のものを用います。
ただし,本日の高値が過去10日間の最高値になっていても、過去5日間(=ホールド期間)に既にも同じことが起きていた場合にはシグナルとはしません。

手仕舞い

シグナルが出てから5日間ホールドして、クローズすることにします。

コード

def initialize(ctx):
    # 設定
    ctx.logger.debug("initialize() called")

    # 過去何日間を観察するか
    ctx.high_term = 10
    # ポジションに対して何%持つか 
    ctx.target = 0.5 
    # ポジションを何日ホールドするか
    ctx.holding_days = 5 

    ctx.configure(
      channels={          # 利用チャンネル
        "jp.stock": {
          "symbols": [
            "jp.stock.1305",
            "jp.stock.9984",
            "jp.stock.9983",
            "jp.stock.7201",
            "jp.stock.9201",
            "jp.stock.9202",
            "jp.stock.7203"
          ],
          "columns": [
            "high_price_adj",]}})    # 高値(株式分割調整後)

    def _BREAK_NEW_HIGH(data):

      # 欠損値を埋める
      hp = data["high_price_adj"].fillna(method="ffill")
      # 過去10日間における最高値を取得
      new_max = hp.rolling(window=ctx.high_term, center=False).max()
      # その最高値が今日の高値と同じかどうかの真偽値
      today_is_new_high = new_max == hp
      # 今日が過去10日間における最高値であり,かつ,過去5日間において最高値が発生していないという真偽値
      buy_signal = (today_is_new_high) & (today_is_new_high.rolling(window=ctx.holding_days, center=False).sum() == 1)

      # pd.Serieseの shift 関数を使って5日前のbuy_signalのシグナルを取得.
      # ここがTrueであれば5日前に取引したという事なので,この日にポジションを閉じる
      # (memo 参照)
      close_signal = buy_signal.shift(ctx.holding_days)


      return {
        "New High":new_max, 
        "buy:sig": buy_signal,
        "close:sig": close_signal,
        }

    # シグナル登録
    ctx.regist_signal("BREAK_NEW_HIGH", _BREAK_NEW_HIGH)

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)
        # New High と 過去10日間の High が本当に同じかどうか確認したかったのでコメントに入れた.
        msg = "買いシグナル: Today's High {0}, Rolling High {1}".format(val["high_price_adj"], val["New High"],)
        sec.order_target_percent(ctx.target, comment= msg)


    # # ポジションクローズ
    df_close = df[df["close:sig"]]
    if not df_close.empty:
      for (sym, val) in df_close.iterrows(): 
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment= "position close")

memo

shift について

shiftは,データをn行ずらすときに使います.コードでは,buy_signalを5シフトした pd.Serise データを close_signal とすることで,5日間ホールドして手仕舞うというシグナルを作っています.

イメージはこんな感じです.

2018-07-27-18:00:25.jpg

結果

2018-07-27-18:11:51.jpg

感想など

  • 銘柄選定はQuantXプロジェクトを新規作成すると自動生成されるサンプルコードに使われている銘柄をそのまま使っています.
  • 高値で見るのではなく,終値で見たほうがいいのでは?と思いました.
  • shift とは仲良くしていきたい.
  • 台風12号が心配

免責注意事項

  • このコードに基づき投資した結果、損害が発生しても,一切責任を持ちません.
  • このコードが正しく機能する保証は一切致しません.
  • このアルゴリズムを勧めているわけではありません.あくまで python のサンプルコードとして掲載しているだけです.
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away