トレード戦略の種類

基本的なトレード戦略の種類について述べる。下のSlideShareによると、5つの基本的なクオンツ戦略があるという。

http://www.slideshare.net/JessStauth/d-30965323(p4)

これによると、戦略は

  1. 平均回帰戦略:上がるものは下がる。

  2. モメンタム戦略:トレンドは友である。

  3. バリュー戦略:安く買って高く売る。

  4. センチメント戦略:噂で買って事実で売る。

  5. 季節性戦略:5月に売る。

の5種類に分類される。

ここでは私の独断と偏見による解釈を用いて、各戦略について簡単に説明する。

平均回帰戦略(上がるものは下がる)

上がるものも永遠に上がり続けることはない。いつかは必ず下がるものである。下がるものも永遠に下がり続けることはない。いつかは必ず上がるものである。

上がったものは下がり、下がったものは上がって、いずれ平均に戻ってくる。そこで、平均より下がれば買い、上がれば売る。これが平均回帰戦略であり、つまりは逆張りである。

ところで、平均回帰戦略について、平均の下で買い、上で売れば必ず勝てるのではないか、と勘違いする初心者が時々いる。だが、実際にはそうはいかない。平均自体も動くからである。

例えば、平均の下で買っても平均が下がり続けることがある。そして、価格が平均に戻ったときには平均は買った価格より下になっていることもあるのである。

また、平均の上で売っても平均が上がり続けることがある。そして、価格が平均に戻ったときには平均は売った価格より上になっていることもあるのである。

平均回帰戦略で勝つためには平均自体の動きが水平に近くなるタイミングを測る必要がある。

モメンタム戦略(トレンドは友である)

トレンドは友、というのはtrendとfriendをかけた洒落である。米国の投資家ジョージ・ソロスの言葉らしい。トレンドとは仲良くしろ、逆らうな、従え、ということのようだ。つまりはトレンドフォロー、順張りである。

平均回帰戦略の逆で、上がれば、その勢い、つまりモメンタムに付いて行って買い、下がれば、そのモメンタムに付いて行って売るのである。では、順張りと逆張り、どちらの戦略が正しいのだろうか。

順張りは正しいが、逆張りは間違っている、というような意見をよく見かける。だが、それは違うと私は考えている。値動きというのは時には平均回帰的であり、時にはモメンタム的であるものだ。したがって状況に合った戦略を採用しなければならない。とはいえ、言うは易く行うは難し、ではある。

バリュー戦略(安く買って高く売る)

「安く買って高く売る」を「下がったら買って上がったら売る」と解してはいけないのだろう。それだと平均回帰戦略と変わらない。「価格が本来の価値より安ければ買い、高ければ売る」と解すべきなのだろう。

本来の価値を知るためには価格以外の指標が必要である。この辺が過去の価格さえ分かればよい平均回帰戦略との違いである。FXの場合、各国の経済指標などを見ることになるのだろうか。

経済指標は少なくとも短期トレードでは使いにくい。取引する通貨ペア以外の通貨ペアの価格を用い、取引する通貨ペアのあるべき価格を算出するというのはどうか。私はそれより高いか安いかで売買するという手法をバリュー戦略としてもいいのではないかと考えている。

センチメント戦略(噂で買って事実で売る)

「噂で買って事実で売る」とは、例えば米国の利上げ観測が持ち上がったらドルが高くなるだろうと予測して買う。そして、実際に利上げが決まったらもはやこれ以上は高くならないだろうと予測して売るのである。

だが、センチメントをどのように測るかというのは簡単ではない。テキストなどを用いた定性分析も必要になるだろう。

季節性戦略(5月に売る)

「5月に売る」というのは株価は5月以降に下がる傾向があるので、5月になったら売るということである。実際に5月以降に下がる傾向があるのかは怪しい。だが、年、四半期、月、週、日などを通した周期性があると考えて、それに基づいた売買を行うのが季節性戦略である。

単に時期によって上がりやすい、下がりやすいということだけが季節性ではない。平均回帰的である、モメンタム的である、というのも季節性である。

商品市場では農作物やエネルギーなど、季節によって需要や供給が大きく変化するものがあるだろう。そのような場合、季節性を期待できる。

FXにおける季節性は商慣習に基づくものが多いのではないだろうか。日本の仲値やロンドンフィキシングなどである。しかし、商慣習も一定不変というわけではないことには注意が必要である。

(2017/03/09更新)

平均回帰戦略

平均回帰戦略を作成してみる。

トレンドは敵

「トレンドは友」と言われるが、平均回帰戦略ではトレンドは敵である。単に売られ過ぎを買い、買われ過ぎを売るというだけでは、なかなか勝てる戦略にはならない。トレンドが発生すると、それまでに稼いだ利益はごっそり持って行かれてしまう。

トレンドを回避する方法としては

  1. トレンド系指標でトレンドの方向を確認して、それに逆らわない形でエントリーする
  2. より長い計算期間でトレンドの方向を確認して、それに逆らわない形でエントリーする
  3. トレンドの変換を確認してからエントリーする

といったことがテクニカル分析ではよく言われる。

ただ、私の経験上、少なくとも短期トレードでは1、2は役に立たず、3は利益の幅を縮小して結局勝てない、という印象が強い。

トレンドは回避するのではなくてやり過ごす

私はトレンドを回避するよりもやり過ごすのが有効だと考えている。そもそも、トレンドは発生の初期段階で認識することは難しい。トレンドが発生したことを認識できたときには、もはやトレンドに乗るには遅すぎ、といって反転するかいなかは分からないという微妙なタイミングである。

だが、トレンドは決して永続しない。トレンドの発生を確認し、しばらく待てばトレンドはいずれ収束する。少なくとも、それまでに稼いだ利益をごっそり持って行ってしまうほどの勢いは残されていないのである。

平均回帰戦略の売買ルール

以上の考えに基づき、以下のような売買ルールを考えてみる。

買いエントリー

  1. zスコアがマイナスのエントリー閾値以下、かつ、
  2. トレンド期間がマイナスのフィルター閾値以下。

売りエントリー

  1. zスコアがプラスのエントリー閾値以上、かつ、
  2. トレンド期間がプラスのフィルター閾値以上。

買いエグジット

  • zスコアが0以上。

売りエグジット

  • zスコアが0以下。

備考

  1. この記事のzスコアとは終値を移動平均で減じ、それを移動標準偏差で除したものである。。
  2. この記事のトレンド期間とは価格が連続して移動平均の上に位置する期間(符号はプラス)、または下に位置する期間(符号はマイナス)のことである。

サンプルプログラム

上述の売買ルールに基づいて作成したサンプルプログラムは以下の通りである。

# coding: utf-8

import forex_system as fs

LOTS = 0.1

# パラメータの設定
MINUTE = 60
ENTRY_THRESHOLD = 0.5
FILTER_THRESHOLD = 2.0
PARAMETER = [MINUTE, ENTRY_THRESHOLD, FILTER_THRESHOLD]

# 最適化の設定
START_MINUTE = 60
END_MINUTE = 300
STEP_MINUTE = 60
START_ENTRY_THRESHOLD = 0.5
END_ENTRY_THRESHOLD = 2.5
STEP_ENTRY_THRESHOLD = 0.5
START_FILTER_THRESHOLD = 0.5
END_FILTER_THRESHOLD = 2.5
STEP_FILTER_THRESHOLD = 0.5
RRANGES = (
    slice(START_MINUTE, END_MINUTE, STEP_MINUTE),
    slice(START_ENTRY_THRESHOLD, END_ENTRY_THRESHOLD, STEP_ENTRY_THRESHOLD),
    slice(START_FILTER_THRESHOLD, END_FILTER_THRESHOLD, STEP_FILTER_THRESHOLD),
)

def strategy(parameter, symbol, timeframe):
    '''戦略を記述する。
    Args:
        parameter: パラメーター。
        symbol: 通貨ペア。
        timeframe: 期間。
    Returns:
        シグナル。
    '''
    # パラメーターを格納する。
    minute = int(parameter[0])
    entry_threshold = float(parameter[1])
    filter_threshold = float(parameter[2])
    # 戦略を記述する。
    period = fs.convert_minute2period(minute, timeframe)
    slope = 0.608286152451
    intercept = -1.1255204743
    divisor = slope * period + intercept
    zscore1 = fs.i_zscore(symbol, timeframe, period, 'MODE_SMA', 1)
    bandwalk1 = (fs.i_bandwalk(symbol, timeframe, period, 'MODE_SMA', 1)
        / divisor)
    buy_entry = (
        (zscore1 <= -entry_threshold) &
        (bandwalk1 <= -filter_threshold)
        )
    buy_exit = zscore1 >= 0.0
    sell_entry = (
        (zscore1 >= entry_threshold) &
        (bandwalk1 >= filter_threshold)
        )
    sell_exit = zscore1 <= 0.0

    return (symbol, timeframe, buy_entry, buy_exit, sell_entry, sell_exit,
            LOTS, 0, 0)


これをSpyderの「エディタ」にコピー・アンド・ペーストし、ファイル名を「mean_reversion.py」として「~/py」フォルダーに保存する。

売買ルールの検証

では、このサンプルプログラムを使って売買ルールの検証を行ってみる。

  • EA: mean_reversion
  • 通貨ペア: USDJPY
  • スプレッド: 0.4pips
  • 足の種類: 5分足
  • 開始日: 2013年1月1日
  • 終了日: 2016年12月31日
  • 最適化: ウォークフォワードテスト

という設定である。

In [1]:
%run -t ~/py/backtest.py --ea1 mean_reversion --symbol1 USDJPY --spread1 0.4 --timeframe 5 --start 2013.01.01 --end 2016.12.31 --optimization 2


    start_test    end_test trades    apr sharpe    kelly drawdowns durations   parameter1 weights
0   2013.12.27  2014.01.25    117 -0.001 -0.004   -0.096     0.012        18   [1.5, 0.5]   [1.0]
1   2014.01.26  2014.02.24    123   0.35  9.565  264.891     0.006         4   [1.5, 0.5]   [1.0]
2   2014.02.25  2014.03.26    111  0.196  6.653  227.406     0.005         7   [1.5, 0.5]   [1.0]
3   2014.03.27  2014.04.25    124  0.095  3.348  117.649     0.005         8   [1.5, 0.5]   [1.0]
4   2014.04.26  2014.05.25    103  0.011  0.528   24.182     0.005         7   [1.5, 0.5]   [1.0]
5   2014.05.26  2014.06.24    114  0.101  6.127   373.18     0.002         2   [1.5, 0.5]   [1.0]
6   2014.06.25  2014.07.24    113  0.007  0.465   30.847     0.005        17   [1.5, 0.5]   [1.0]
7   2014.07.25  2014.08.23    112   0.04  2.006   99.139     0.003         7   [1.5, 0.5]   [1.0]
8   2014.08.24  2014.09.22    117 -0.034 -1.099   -36.17     0.013        19   [1.5, 0.5]   [1.0]
9   2014.09.23  2014.10.22    138  0.386  7.796  159.464     0.015         2   [1.5, 0.5]   [1.0]
10  2014.10.23  2014.11.21    123  0.167  3.612   78.105     0.014         8   [1.5, 0.5]   [1.0]
11  2014.11.22  2014.12.21    119   0.37  6.122  102.382     0.015         4   [1.5, 0.5]   [1.0]
12  2014.12.22  2015.01.20    121  0.063   1.17   21.379      0.01        13   [1.5, 0.5]   [1.0]
13  2015.01.21  2015.02.19    116  0.342  9.023  241.041     0.005         3   [1.5, 0.5]   [1.0]
14  2015.02.20  2015.03.21    103    0.1  2.466   60.636     0.011         3   [1.5, 0.5]   [1.0]
15  2015.03.22  2015.04.20    128 -0.014 -0.401  -12.087     0.012        17   [1.5, 0.5]   [1.0]
16  2015.04.21  2015.05.20    123  0.083  2.707    88.46     0.006         5   [1.5, 0.5]   [1.0]
17  2015.05.21  2015.06.19     61  0.096  4.099  175.404     0.004         5  [1.5, 0.75]   [1.0]
18  2015.06.20  2015.07.19     61  0.107  4.547  193.778     0.005         5  [1.5, 0.75]   [1.0]
19  2015.07.20  2015.08.18     26 -0.013 -0.811  -50.338     0.006        10   [1.5, 1.0]   [1.0]
20  2015.08.19  2015.09.17     25  0.018  0.598   19.913     0.006        11   [1.5, 1.0]   [1.0]
21  2015.09.18  2015.10.17     47 -0.041   -1.8  -78.528     0.007        12  [1.5, 0.75]   [1.0]
22  2015.10.18  2015.11.16     27  0.031  1.857  110.617     0.004         5   [1.5, 1.0]   [1.0]
23  2015.11.17  2015.12.16     36  0.018  1.124     69.4     0.005         6   [1.5, 1.0]   [1.0]
24  2015.12.17  2016.01.15     62  0.256  9.889  386.208     0.004         4  [1.5, 0.75]   [1.0]
25  2016.01.16  2016.02.14     55  0.207  4.995  121.295     0.007         5  [1.5, 0.75]   [1.0]
26  2016.02.15  2016.03.15     68  0.104  2.922   81.683     0.008         6  [1.5, 0.75]   [1.0]
27  2016.03.16  2016.04.14     28  0.048  2.316  111.077     0.005        17   [1.5, 1.0]   [1.0]
28  2016.04.15  2016.05.14     56  0.051  1.484   43.073     0.009        15  [1.5, 0.75]   [1.0]
29  2016.05.15  2016.06.13     64  0.092  2.781   84.173     0.005        10  [1.5, 0.75]   [1.0]
30  2016.06.14  2016.07.13     51 -0.064 -1.383  -30.152     0.013        11  [1.5, 0.75]   [1.0]
31  2016.07.14  2016.08.12    120 -0.108 -1.604  -24.186     0.021        14   [1.5, 0.5]   [1.0]
32  2016.08.13  2016.09.11    106  0.108  2.632   64.107     0.013        10   [1.5, 0.5]   [1.0]
33  2016.09.12  2016.10.11    111  0.258  5.663  125.334     0.007         7   [1.5, 0.5]   [1.0]
34  2016.10.12  2016.11.10    112 -0.264 -3.963  -59.334      0.03        12   [1.5, 0.5]   [1.0]
35  2016.11.11  2016.12.10    122   0.24   4.34   78.812     0.012         5   [1.5, 0.5]   [1.0]
36  2013.12.27  2016.12.10   3243  0.108  2.518   67.426      0.03        78



IPython CPU timings (estimated):
  User   :     412.88 s.
  System :      16.30 s.
Wall time:     364.52 s.


年率は10.8%、シャープレシオは2.52となっており、まずまずである。

(2017/03/18更新)

順張り逆張り、利食い損切り、ナンピンについて

順張りは正しいが、逆張りは間違っている、といった主張を時々見かける。また、遅く利食い、早く損切りするのは正しいが、早く利食い、遅く損切りするのは間違っている、といった主張も時々見かける。さらにナンピンは間違っている、といった主張も時々見かける。果たしてそうなのか。

それらについて私なりの考えをまとめてみた。あくまでも私の見方であって、これが正しいと主張するつもりはない。

順張りとは

順張りとは上がれば買い、下がれば売ることである。

逆張りとは

逆張りとは下がれば買い、上がれば売ることである。

どのようなとき、順張りは正当化されるか

上がればさらに上がる、下がればさらに下がるとトレーダーが判断しているとき、つまり順張り有利と判断しているとき、順張りは正当化される。その判断が正しいかいなかは問わない。

トレーダーが順張り有利と判断しているとき、上がれば買い、下がれば売るのは例え損失という結果をもたらしたとしても合理的な行動である。

トレーダーが順張り有利と判断しているとき、上がれば売り、下がれば買うのは例え利益という結果をもたらしたとしても合理的な行動ではない。

どのようなとき、逆張りは正当化されるか

下がれば反転して上がる、上がれば反転して下がるとトレーダーが判断しているとき、つまり逆張り有利と判断しているとき、逆張りは正当化される。その判断が正しいかいなかは問わない。

トレーダーが逆張り有利と判断しているとき、下がれば買い、上がれば売るのは例え損失という結果をもたらしたとしても合理的な行動である。

トレーダーが逆張り有利と判断しているとき、下がれば売り、上がれば買うのは例え利益という結果をもたらしたとしても合理的な行動ではない。

利食いとは

利食いとは損益が利益となっている状態でエグジットすることである。

損切りとは

損切りとは損益が損失となっている状態でエグジットすることである。

どのようなとき、利食いは正当化されるか

順張りで買って上がったとき、トレーダーはさらに上がると予想すべきだから、ここで利食うのは合理的な行動ではなく、正当化されない。

順張りで売って下がったとき、トレーダーはさらに下がると予想すべきだから、ここで利食うのは合理的な行動ではなく、正当化されない。

逆張りで買って上がったとき、トレーダーは反転して下がると予想すべきだから、ここで利食うのは合理的な行動であり、正当化される。

逆張りで売って下がったとき、トレーダーは反転して上がると予想すべきだから、ここで利食うのは合理的な行動であり、正当化される。

どのようなとき、損切りは正当化されるか

順張りで買って下がったとき、トレーダーはさらに下がると予想すべきだから、ここで損切るのは合理的な行動であり、正当化される。

順張りで売って上がったとき、トレーダーはさらに上がると予想すべきだから、ここで損切るのは合理的な行動であり、正当化される。

逆張りで買って下がったとき、トレーダーは反転して上がると予想すべきだから、ここで損切るのは合理的な行動ではなく、正当化されない。

逆張りで売って上がったとき、トレーダーは反転して下がると予想すべきだから、ここで損切るのは合理的な行動ではなく、正当化されない。

どのようなとき、順張りの利食いは正当化されるか

順張りで買って上がり、かつ順張り有利から逆張り有利へのレジームスイッチが発生したと判断したとき、トレーダーは反転して下がると予想すべきだから、ここで利食うのは合理的な行動であり、正当化される。

順張りで売って下がり、かつ順張り有利から逆張り有利へのレジームスイッチが発生したと判断したとき、トレーダーは反転して上がると予想すべきだから、ここで利食うのは合理的な行動であり、正当化される。

どのようなとき、逆張りの損切りは正当化されるか

逆張りで買って下がり、かつ逆張り有利から順張り有利へのレジームスイッチが発生したと判断したとき、トレーダーはさらに下がると予想すべきだから、ここで損切るのは合理的な行動であり、正当化される。

逆張りで売って上がり、かつ逆張り有利から順張り有利へのレジームスイッチが発生したと判断したとき、トレーダーはさらに上がると予想すべきだから、ここで損切るのは合理的な行動であり、正当化される。

ナンピンとは

ナンピンとは買った後に下がったら更に買い増し、売った後に上がったら更に売り増すことである。

どのようなとき、ナンピンは正当化されるか

トレーダーが逆張り有利と判断しているとき、ナンピンは正当化される。その判断が正しいかいなかは問わない。

トレーダーが順張り有利と判断しているとき、ナンピンは正当化されない。

買ったら下がってしまい、売ったら上がってしまって含み損を抱え、逆張り有利という判断もなく、ただ反転することを祈っているだけのとき、ナンピンは正当化されない。

(2016/11/29更新)

期待利益がマイナスの戦略は捨てるべきか

本題に入る前に基本的なことを確認しておく。

期待利益とシャープレシオの関係

ここに1年当たり100トレード、1トレード当たりの期待利益が0.1%、リスクが1.0%の戦略があるとする。単純化して考えると、1年当たりの期待利益は0.1% * 100 = 10.0%、リスクは√Tルールに基づけば1.0% * sqrt(100) = 10.0%となる。したがって、シャープレシオは10.0 / 10.0 = 1.0となる。これを戦略Aとする。

一方、1年当たり100トレード、1トレード当たりの期待利益が0.2%、リスクが4.0%の戦略があるとする。同様に考えて、1年当たりの期待利益は0.2% * 100 = 20.0%、リスクは4.0% * sqrt(100) = 40.0%となる。したがって、シャープレシオは20.0 / 40.0 = 0.5となる。これを戦略Bとする。

戦略Bの期待利益は戦略Aの2倍である。では戦略Bのほうが優れているかといえばそういうわけではない。1年後の利益はリスクも考慮すると1年当たりの期待利益 ± 1年当たりのリスクであるから、戦略Aは10% ± 10%、つまり0%〜20%となる。一方、戦略Bは20% ± 40%、つまり-20%〜60%となる。

都合よく考えると、戦略Aは20%、戦略Bは60%の利益だから戦略Bのほうがいいということになるが、果たしてそうか。逆に都合悪く考えると、戦略Aは0%、戦略Bは-20%となり、戦略Aは単に利益が出ないだけだが、戦略Bは-20%の損失である。だが、リスクを等しくしないと比較できないのである。

戦略Aで戦略Bと同じ4.0%のリスクを覚悟できるなら、投資額を4倍にすればいい(資金があればだが)。すると、期待利益も4倍になり、1年当たりの期待利益は0.4% * 100 = 40%、リスクは4.0% *sqrt(100) = 40%となる。1年後のリスクは40% ± 40%、つまり0〜80%となり、都合よく考えても、都合悪く考えても戦略Aは戦略Bより優れている。

つまり、期待利益が大きいかどうかが大事なのではなく、期待利益とリスクの比、つまりシャープレシオが大きいかどうかが大事なのである。期待利益は小さいがシャープレシオが大きい戦略は、期待利益は大きいがシャープレシオが小さい戦略と同じリスクを負うことで後者より大きい利益を生むことができるのである(机上の計算では)。

期待利益がマイナスの戦略でも役に立つ場合がある

さて、期待利益とシャープレシオの関係を確認したところで本題に入る。

ここに勝つ場合は+1、負ける場合は-1で一定で、1年当たり12回勝ち、8回負けるという戦略Aがあるとする。計算すると、期待利益は0.2、リスクは0.98、シャープレシオは0.91となる。

一方、勝つ場合は+0.5、負ける場合は-0.5で一定で、戦略Aが勝てば必ず負け、負ければ必ず勝つという戦略Bがあるとする。計算すると、期待利益は-0.1、リスクは0.49、シャープレシオは-0.91となる。

戦略Aと戦略Bの相関係数を求めると-1.0となる。勝敗が正反対なのであるから当然である。

ここで戦略Aと戦略Bを合わせた戦略Cを考えてみる。計算すると、期待利益は0.1、リスクは0.49、シャープレシオは0.91となる。戦略Aと比べると、期待利益は半減したが、リスクも半減したのでシャープレシオは変わらない。したがって、戦略Cはシャープレシオにおいて戦略Aと同等である。戦略Cが投資額を倍にして戦略Aと同じリスクを負うなら、期待利益も同じになる(資金の使い方としては非効率だが)。

ところで、戦略Bの負けを1つだけ勝ちだったことにしてみる。再計算すると、期待利益は-0.05、リスクは0.49、シャープレシオは-0.45となる。元の戦略と比べると、期待利益は半減したが、リスクはそのままなので、シャープレシオも半減する。ただし、期待利益はマイナスなので、これは改善である。

戦略Aと新しい戦略Bの相関係数を求めると-0.91となる。勝敗が完全には反対でないので、これも当然である。

そして、戦略Aにこの新しい戦略Bを合わせて新しい戦略Cを考えてみる。再計算すると、期待利益は0.15、リスクは0.57、シャープレシオは1.17となる。戦略Aと比べると、期待利益は減少しているが、リスクはそれ以上に減少しているので、シャープレシオは大きくなっている。したがって、新しい戦略Cはシャープレシオにおいて戦略Aより優れている。

つまり、新しい戦略Bを加えることによって戦略Aは改善されたのである。だが、新しい戦略Bの期待利益は-0.05であり、マイナスである。にもかかわらず、戦略Aを改善したのだ。

したがって、期待利益がマイナスの戦略でも役に立つ場合があると言える。ならば、いきなり捨てたりはせずに使い道がないか考えてみてもいいのではないだろうか。

a =  [ 1  1  1  1  1  1  1  1  1  1  1  1 -1 -1 -1 -1 -1 -1 -1 -1]
mean_a =  0.2
std_a =  0.979795897113
sharpe_a =  0.912870929175
b =  [-0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5  0.5  0.5  0.5
  0.5  0.5  0.5  0.5  0.5]
mean_b =  -0.1
std_b =  0.489897948557
sharpe_b =  -0.912870929175
cor_ab =  -1.0
c =  [ 0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5 -0.5 -0.5 -0.5
 -0.5 -0.5 -0.5 -0.5 -0.5]
mean_c =  0.1
std_c =  0.489897948557
sharpe_c =  0.912870929175
b2 =  [ 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5  0.5  0.5  0.5
  0.5  0.5  0.5  0.5  0.5]
mean_b2 =  -0.05
std_b2 =  0.497493718553
sharpe_b2 =  -0.449466574975
cor_ab2 =  -0.902670933848
c2 =  [ 1.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5 -0.5 -0.5 -0.5
 -0.5 -0.5 -0.5 -0.5 -0.5]
mean_c2 =  0.15
std_c2 =  0.572276157113
sharpe_c2 =  1.17219699775

サンプルプログラム

○以下のコマンドをSpyderの「IPython console」にコピー&ペーストして「Enter」キーを2回押す。

# coding: utf-8

import numpy as np

a = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, -1, -1, -1, -1, -1, -1, -1, -1])
print('a = ', a)
mean_a = np.mean(a)
print('mean_a = ', mean_a)
std_a = np.std(a)
print('std_a = ', std_a)
sharpe_a = mean_a / std_a * np.sqrt(20)
print('sharpe_a = ', sharpe_a)

b = np.array([-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
              -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
print('b = ', b)
mean_b = np.mean(b)
print('mean_b = ', mean_b)
std_b = np.std(b)
print('std_b = ', std_b)
sharpe_b = mean_b / std_b * np.sqrt(20)
print('sharpe_b = ', sharpe_b)

cor_ab = np.corrcoef(a, b)[0][1]
print('cor_ab = ', cor_ab)

c = a + b
print('c = ', c)
mean_c = np.mean(c)
print('mean_c = ', mean_c)
std_c = np.std(c)
print('std_c = ', std_c)
sharpe_c = mean_c / std_c * np.sqrt(20)
print('sharpe_c = ', sharpe_c)

b[0] = 0.5
b2 = b
print('b2 = ', b2)
mean_b2 = np.mean(b2)
print('mean_b2 = ', mean_b2)
std_b2 = np.std(b2)
print('std_b2 = ', std_b2)
sharpe_b2 = mean_b2 / std_b2 * np.sqrt(20)
print('sharpe_b2 = ', sharpe_b2)

cor_ab2 = np.corrcoef(a, b2)[0][1]
print('cor_ab2 = ', cor_ab2)

c2 = a + b2
print('c2 = ', c2)
mean_c2 = np.mean(c2)
print('mean_c2 = ', mean_c2)
std_c2 = np.std(c2)
print('std_c2 = ', std_c2)
sharpe_c2 = mean_c2 / std_c2 * np.sqrt(20)
print('sharpe_c2 = ', sharpe_c2)
(2016/11/15更新)