マーケットマイクロストラクチャーの研究その3

LINEで送る
Pocket

前々回、前回に続いて3連休企画第三弾です。

本日は昨日、一昨日と3日間準備してきた自動売買の集大成として、実際にアルゴリズムを動かしてみた結果を公表したいと思います。

3連休が始まりましたね。 この記事を書いてるのは初日の11/23夜なので、33%が終わってしまいました。 今夜は日本では祝日ですが、夜は...
前回の続きです。 3連休はアルゴリズムトレードで利益が出せるかという遊びをやっています。 前回(昨日)は全体のフロー...

ちなみに、初日に掲げた目標は大きく3つありました。

  • 米国株高配当ディフェンシブ投資を実践している管理人にとって、アルゴリズムトレードによる安定的な収益基盤を確立できるのか
  • ビットコインは投機ブームが終焉に向かい、今後は価格が調整し続けていく可能性が高いが、マーケットマイクロストラクチャーに着目したトレードは有効か
  • 最後に3連休の初日の課題として自己研鑽の一貫で分析能力向上が目的です。

1、2番目はそのままですが、個人的には、この3日間でpythonという言語を使い込んで分析能力を養えたというものが一番大きい成果だったのかもしれません。

スクリプト言語は使いこなして始めて意味があるので、使ったことがある、動かしてみたことがあるだけでは何の意味もありません。

正直、このブログを書きながら検証を進めていると、アルゴで収益化を図るのは難しそうだなという思う場面もありましたが、その度にデータをよく見ることで、pythonをある程度自由自在に使いこなせるようになっていきました。

最初は実行環境を整えるところから始まり、エディターも今メインで使っているpycharmのほかにもatomjupyterなども試してみました。

当然、言語の特徴や文法もゼロベースで覚えつつ、3日間でアルゴリズムで取引するレベルまで持っていくのは少し大変な作業でもありました。

その反面、Pythonの便利なデータ分析・集計用、グラフ描画用のライブラリのnumpypandasの習得により、今後、様々な分析作業が楽になると思えば有意義な時間の過ごし方だったかもしれません。

言語の習得や分析能力という小手先の技術力向上はぶっちゃけどうでもよくて、短期間で新しいことに挑戦し、結果を出すということが重要だと思っています。

前置きが長くなってしまいましたが、昨日までの二日間で準備してきた、アルゴリズムのざっくりとした流れ(1日目)と統計的手法によるプライシングやタイミング(2日目)を用いた実証研究の結果報告をしたいと思います。

実際の場に注文を出して約定できたかどうかをシミュレーションしてみた結果が以下です。

横軸は裁定取引の往復売買の回数で、シミュレーション期間としては約30分程度です。

また投資金額は1btcなのでこの時の価格が40万円程度でした。

約40万円の元手を使って30分で累計リターンとして2.5%が獲得できたことになります。

シミュレーションを実施して思ったこととして、指値金額を出してから約定するまでに時間がかかることが多かったです。

売買を記録したログを見ると、1回の裁定で長い時では2分程度かかっていた場合もあります。

これは指値で注文を出してから2分間約定できなかったことを表しています。

これ以上長くなるとアルゴでやる意味もないので、損切りをしたほうがいいかもしれませんね。

今回のアルゴリズムでは3分経過しても約定できなければ注文をキャンセルしています。

買い注文が約定したあとに売り注文が成立しなかった場合はポジションをクローズしています。

グラフが下がることもあるのはこうした損切りによるものです。

現状の裁定取引では買い注文の指値を簡単のため過去の30tickの平均約定単価と標準偏差(と直近高値と安値のスプレッド)で決定しているため待機時間が多く、時間効率が低いです。

こうした買い注文の指値をより精緻に決めることで待機時間を短縮したり、売り注文についても価格の変動方向からより高い売り注文に動的に修正をかけるなど工夫の余地は山ほどあります。

最終的には東証のコロケーションサービスを使っている業者のようにapi提供サーバーの近くでアルゴリズムトレードを実施するなど、物理的な距離が問題にせざるを得ないほどアルゴリズムを洗練させていきたいですね。

最後にアルゴリズムのコアとなる裁定注文を掲載しておきます。

#この値段を場に出してから実際の直近のcloseが下回れば約定した事になる
wait_time = 5#注文出してから約定を待つまでのシミュレーション上の時間
trial_num = 30
sigma_magnification = 1
trial_buy = 0
sum_buy=0
sum_success = 0
sum_profit_loss = 0
df_profit = pd.DataFrame()

#時系列で損益を保存するdf
#df_profit.append(pd.DataFrame(datetime=0,))

for i in range(trial_num):
    trial_buy += 1
    print("買い注文 = " + str(trial_buy))
    ps = get_ticks()  # tick
    now_price = int(ps.price.tail(1))
    mean_price = int(ps.price.tail(30).mean())
    std_price = int(ps.price.tail(30).std())
    buy_price = float(now_price - std_price * sigma_magnification)
    print("buy_price = " + str(buy_price) + ", against now price = " + str(now_price) + ", diff = " + str(now_price - buy_price))
    buy_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S+09:00")
    success_buy = False

    for buy_trial in range(trial_num):
        if success_buy:
            break

        print("try to buy , wait(" + str(wait_time) + "sec)...")
        sleep(wait_time)#sec
        ps2 = get_ticks()
        ps2 = ps2[ps2.time >= buy_time]

        if len(ps2.index) == 0:
            print("no transaction after buy order")
            continue


        # now_low2 = float(ps2.low.tail(1))

        now_low2 = float(ps2.price.min())
        print("low_price = " + str(now_low2))
        if buy_price >= now_low2:# 約定した場合
            success_buy = True
            success_sell = False
            sum_buy += 1#購入回数
            print("success to buy at " + str(buy_price))
            #買付時刻
            buy_tr_time = ps2.time[ps2.price<=buy_price].min() sell_price = buy_price + std_price * sigma_magnification / 2 sell_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S+09:00") for sell_trial in range(10): sleep(wait_time) #ps3 = get_minutes_price(arg_chart_type=60) ps3 = get_ticks() #ps3 = ps3[ps3.time >= sell_time]
                ps3 = ps3[ps3.time >= buy_tr_time]

                if len(ps3.index) == 0:
                    print("no transaction after sell order")
                    continue
                print("try to sell(wait {0}sec) : at price = {1}, against now = {2}".format(str(wait_time),str(sell_price), str(float(ps3.price.tail(1)))))
                #now_high3 = int(ps3.high.tail(1))
                now_high3 = int(ps3.price.max())

                #利確したかどうか
                if sell_price <= now_high3: profit = sell_price - buy_price sum_profit_loss = sum_profit_loss + profit print("arbitrage success! : profit = " + str(profit)) success_sell = True sum_success += 1 sell_tr_time = ps3[(ps3.time > buy_tr_time) & (ps3.price <= sell_price)].time.min()
                    break
            if not success_sell:
                loss = buy_price - float(ps3.price.head(1)) #<0
                sum_profit_loss = sum_profit_loss + loss
                print("arbitrage failed. loss = " + str(loss) + ", buy=" + str(buy_price) + ", now=" + str(float(ps3.price.head(1))))

    df_tmp = pd.DataFrame({ 'buy_time' : buy_time,
                            'sell_time' : sell_time,
                            'buy_tr_time' : buy_tr_time,
                            'sell_tr_time': sell_tr_time,
                            'buy'  : pd.Series(buy_price,index=list(range(1)),dtype='float32'),
                            'sell' : sell_price,
                            'profit': profit,
                            'sum_profit' : sum_profit_loss})
    df_profit = df_profit.append(df_tmp, ignore_index=True)

LINEで送る
Pocket

The following two tabs change content below.

パウエル五郎

名前:パウエル五郎 年齢:30代 経歴:サラリーマン時代は赤い銀行で国内外の株式のアナリストやファンドマネージャーなど一貫して株式のトレーディングに携わる。 現在は日本株の個人投資家として独立。2016年にアマゾンを購入してからひたすら買い増し、現在はVTなど世界分散投資も実践。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする