Python標準ライブラリ入門 (2017/05/30)

Pythonの標準ライブラリで私自身がよく使うものに限って簡単に説明する。

この記事は内容を随時追加する。

datetime

datetimeのインポート

from datetime import datetime
from datetime import timedelta

str型をdatetime型に変換

a = '2017.01.01 00:00'
print(a)
print(datetime.strptime(a, '%Y.%m.%d %H:%M'))

2017.01.01 00:00
2017-01-01 00:00:00

datetime型をstr型に変換

a = datetime.strptime('2017.01.01 00:00', '%Y.%m.%d %H:%M')
print(a)
print(a.strftime('%Y.%m.%d %H:%M'))

2017-01-01 00:00:00
2017.01.01 00:00

日付の加算・減算

a = datetime.strptime('2017.01.01 00:00', '%Y.%m.%d %H:%M')
b = timedelta(minutes=5)
print(a)
print(b)
print(a + b)
print(a - b)

2017-01-01 00:00:00
0:05:00
2017-01-01 00:05:00
2016-12-31 23:55:00

Pythonで素数を生成 (2017/05/28)

しょうらいのゆめ: りーまんよそうをしょうめいする。

○以下のコマンドをIPythonコンソールに入力して実行する。

import numpy as np

def get_prime_number(n):
    natural_number = np.arange(n) + 1.0
    natural_number[0] = np.nan
    for i in range(1, int(np.floor(n/2))):
        natural_number[(natural_number!=natural_number[i])
        & (natural_number%natural_number[i]==0)] = np.nan
    prime_number = natural_number[~np.isnan(natural_number)]
    prime_number = prime_number.astype(int)
    return prime_number

prime_number = get_prime_number(1000)
print(prime_number)

[  2   3   5 ..., 983 991 997]

勝てない戦略の活用 (2017/05/19)

勝てない戦略でも他の戦略と組み合わせると役に立つ場合がある。複数の戦略を組み合わせる場合、勝てる戦略同士を組み合わせなければならないと思い込んでいる人もいるだろう。だが、かならずしもそうでないことを説明する。

期待利益、リスク、シャープレシオ

本題に入る前に、期待利益、リスク、シャープレシオについて簡単に説明しておく。

ここに1年当たり100トレード、1トレード当たりの期待利益が0.1%、リスクが1.0%の戦略Aがあるとする。リスクフリーレートを考慮せずにシャープレシオを求めると、

\[ 戦略Aの1年当たりの期待利益 = 0.1 \times 100 = 10.0 \] \[ 戦略Aの1年当たりのリスク = 1.0 \times \sqrt{100} = 10.0 \] \[ 戦略Aの1年当たりのシャープレシオ = 10.0 \div 10.0 = 1.0 \]

となる。

一方、1年当たり100トレード、1トレード当たりの期待利益が0.2%、リスクが4.0%の戦略Bがあるとする。同様に考えると、

\[ 戦略Bの1年当たりの期待利益 = 0.2 \times 100 = 20.0 \] \[ 戦略Bの1年当たりのリスク = 4.0 \times \sqrt{100} = 40.0 \] \[ 戦略Bの1年当たりのシャープレシオ = 20.0 \div 40.0 = 0.5 \]

となる。

戦略Bの期待利益は戦略Aの2倍である。では戦略Bのほうが優れているかといえばそういうわけではない。1年後の予想利益はリスクも考慮すると、

\[ 戦略Aの1年後の予想利益 = 10.0 \pm 10.0 \] \[ 戦略Bの1年後の予想利益 = 20.0 \pm 40.0 \]

となる。

都合よく考えると、利益は最大で戦略Aは20%、戦略Bは60%の利益だから戦略Bのほうが良さそうに見える。だが、逆に都合悪く考えると、戦略Aは0%、戦略Bは-20%となり、戦略Aは単に利益が出ないだけだが、戦略Bは-20%の損失である。

都合よく考えるのも都合悪く考えるのも正しくない。リスクを等しくして比較する必要がある。

もし戦略Aで戦略Bと同じ4.0%のリスクを覚悟できるなら、投資額を4倍にすればいい。すると、期待利益も4倍になり、

\[ 戦略Aの1年当たりの期待利益 = 0.4 \times 100 = 40.0 \] \[ 戦略Aの1年当たりのリスク = 4.0 \times \sqrt{100} = 40.0 \] \[ 戦略Aの1年後の予想利益 = 40.0 \pm 40.0 \]

となる。つまり、都合よく考えれば80%の利益、都合悪く考えても0%の利益で、いずれの場合も戦略Aは戦略Bより優れている。

勝てない戦略は役に立たないか

では本題に入る。

ここに勝つ場合は+1、負ける場合は-1で一定で、1年当たり12回勝ち、8回負けるという戦略Cがあるとする。Pythonで計算してみると、

import numpy as np

c = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
              -1])
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)


mean_c =  0.2
std_c =  0.979795897113
sharpe_c =  0.912870929175

で、期待利益は0.2、リスクは0.98、シャープレシオは0.91となる。

一方、勝つ場合は+0.5、負ける場合は-0.5で一定で、戦略Cが勝てば必ず負け、負ければ必ず勝つという戦略Dがあるとする。計算すると

d = 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])
mean_d = np.mean(d)
print('mean_d = ', mean_d)
std_d = np.std(d)
print('std_d = ', std_d)
sharpe_d = mean_d / std_d * np.sqrt(20)
print('sharpe_d = ', sharpe_d)


mean_d =  -0.1
std_d =  0.489897948557
sharpe_d =  -0.912870929175

で、期待利益は-0.1、リスクは0.49、シャープレシオは-0.91となる。

戦略Cと戦略Dの相関係数を求めると、

cor_cd = np.corrcoef(c, d)[0][1]
print('cor_cd = ', cor_cd)


cor_cd =  -1.0

で、-1.0となる。勝敗が正反対なのであるから当然である。

ここで戦略Cと戦略Dを合わせた戦略Eを考えてみる。計算すると、

e = c + d
mean_e = np.mean(e)
print('mean_e = ', mean_e)
std_e = np.std(e)
print('std_e = ', std_e)
sharpe_e = mean_e / std_e * np.sqrt(20)
print('sharpe_e = ', sharpe_e)


mean_e =  0.1
std_e =  0.489897948557
sharpe_e =  0.912870929175

で、期待利益は0.1、リスクは0.49、シャープレシオは0.91となる。戦略Cと比べると、期待利益は半減したが、リスクも半減したのでシャープレシオは変わらない。

したがって、戦略Eはシャープレシオにおいて戦略Cと同等である。戦略Eが投資額を倍にして戦略Cと同じリスクを負うなら、期待利益も同じになる。資金の使い方として非効率である点はここでは無視する。

ところで、戦略Dの負けを1つだけ勝ちだったことにしてみる。再計算すると、

d[0] = 0.5
mean_d = np.mean(d)
print('mean_d = ', mean_d)
std_d = np.std(d)
print('std_d = ', std_d)
sharpe_d = mean_d / std_d * np.sqrt(20)
print('sharpe_d = ', sharpe_d)


mean_d =  -0.05
std_d =  0.497493718553
sharpe_d =  -0.449466574975

で、期待利益は-0.05、リスクは0.49、シャープレシオは-0.45となる。元の戦略と比べると、期待利益は増加したが、リスクはそのままなので、シャープレシオも増加している。

戦略Cと新しい戦略Dの相関係数を求めると、

cor_cd = np.corrcoef(c, d)[0][1]
print('cor_cd = ', cor_cd)


cor_cd =  -0.902670933848

で、-0.90となる。勝敗が完全には反対でないので、これも当然である。

そして、戦略Cにこの新しい戦略Dを合わせて新しい戦略Eを考えてみる。再計算すると、

e = c + d
mean_e = np.mean(e)
print('mean_e = ', mean_e)
std_e = np.std(e)
print('std_e = ', std_e)
sharpe_e = mean_e / std_e * np.sqrt(20)
print('sharpe_e = ', sharpe_e)


mean_e =  0.15
std_e =  0.572276157113
sharpe_e =  1.17219699775

で、期待利益は0.15、リスクは0.57、シャープレシオは1.17となる。戦略Cと比べると、期待利益は減少しているが、リスクはそれ以上に減少しているので、シャープレシオは大きくなっている。

新しい戦略Dの期待利益は-0.05であり、マイナスである。にもかかわらず、戦略Cのパフォーマンスを改善していることが分かる。つまり、勝てない戦略でも役に立つことがあるのである。

理屈はそうだが...

長々と説明したが、理屈はそうでも、いざ実行するとなると心理的にかなり抵抗がある。かく言う私も勝てない戦略を活用してみたいとは思うが(在庫はたくさんあるので)、実際にはやっていない(笑)。

週単位、月単位で勝つためのシャープレシオ (2017/05/14)

あるトレード戦略が週単位、月単位で勝つためにはどの程度のシャープレシオが必要かということを考えてみる。

勝てる戦略とは

例えば、年単位の利益が10%、年単位のリスクが10%だとする。すると、シャープレシオは

\[ sharpe = 0.1 / 0.1 = 1.0 \]

となる。したがって、1年後の想定利益は10±10%、つまり0~20%となる。

ところで、リスクは1σで計算している。したがって、想定利益は68.27%の確率でその範囲内に収まる。つまり1年後の利益がプラスである確率は68.27%以上となる。なぜ68.27%「以上」になるかというと、年単位20%を越える利益となる可能性もあるからである。

もう少し正確には

\[ prob = 68.27 + (100 - 68.27) / 2 = 84.135 \]

で、84.135%となる(手計算なので誤差あり)。もちろん、これは机上の空論だ。だが、一応の目安にはなる。

ここではプラスとなる確率が84.135%以上であれば「勝てる戦略」と見なすことにする。すると、シャープレシオが1.0以上なら年単位では「勝てる戦略」と言える。同様に週単位、月単位のシャープレシオが1.0以上であれば、週単位、月単位で「勝てる戦略」と言える。

シャープレシオの計算式

ここで、週単位、月単位、年単位のシャープレシオの計算式を定義しておく。

ここでは1週間を5営業日、1ヶ月を20営業日、1年を260営業日としておく。また、1日単位の利益をr、1日単位のリスクをsとする。また、リスクフリーレートは考慮しないことにする。

すると、

\[ sharpe_{weekly} = \frac {5r} {\sqrt{5s}} \] \[ sharpe_{manthly} = \frac {20r} {\sqrt{20s}} \] \[ sharpe_{yearly} = \frac {260r} {\sqrt{260s}} \]

となる。

週単位で勝つためのシャープレシオ

では、先ず、週単位のシャープレシオが1.0以上であるには、年単位のシャープレシオがどのくらい以上でなければならないかを考える。

\[ \frac {sharpe_{yearly}} {sharpe_{weekly}} = \frac {\frac {260r} {\sqrt{260s}}} {\frac {5r} {\sqrt{5s}}} \] \[ {sharpe_{weekly}} = 1, \ \frac {sharpe_{yearly}} {1} = \frac {\frac {260r} {\sqrt{260s}}} {\frac {5r} {\sqrt{5s}}} \] \[ sharpe_{yearly} = \frac {\frac {260r} {\sqrt{260s}}} {\frac {5r} {\sqrt{5s}}} \] \[ = \frac {260r} {\sqrt{260s}} \times \frac {\sqrt{5s}} {5r} \] \[ = \frac {52} {\sqrt{52}} \times \frac {1} {1} \] \[ = \frac {52} {\sqrt{52}} \] \[ = \frac {52 \times \sqrt{52}} {\sqrt{52} \times \sqrt{52}} \] \[ = \frac {52 \times \sqrt{52}} {52} \] \[ = \sqrt{52} \] \[ \approx 7.21 \]

となる。つまり、週単位のシャープレシオが1.0以上であるには、年単位のシャープレシオが約7.21以上である必要がある。

月単位で勝つためのシャープレシオ

次に、月単位のシャープレシオが1.0以上であるには、年単位のシャープレシオがどのくらい以上でなければならないかを考える。

\[ \frac {sharpe_{yearly}} {sharpe_{monthly}} = \frac {\frac {260r} {\sqrt{260s}}} {\frac {20r} {\sqrt{20s}}} \] \[ {sharpe_{monthly}} = 1, \ \frac {sharpe_{yearly}} {1} = \frac {\frac {260r} {\sqrt{260s}}} {\frac {20r} {\sqrt{20s}}} \] \[ sharpe_{yearly} = \frac {\frac {260r} {\sqrt{260s}}} {\frac {20r} {\sqrt{20s}}} \] \[ = \frac {260r} {\sqrt{260s}} \times \frac {\sqrt{20s}} {20r} \] \[ = \frac {13} {\sqrt{13}} \times \frac {1} {1} \] \[ = \frac {13} {\sqrt{13}} \] \[ = \frac {13 \times \sqrt{13}} {\sqrt{13} \times \sqrt{13}} \] \[ = \frac {13 \times \sqrt{13}} {13} \] \[ = \sqrt{13} \] \[ \approx 3.61 \]

となる。つまり、月単位のシャープレシオが1.0以上であるには、年単位のシャープレシオが約3.61以上である必要がある。

まとめ

年単位のシャープレシオが3.61以上というのはなかなか難しい。まして、7.21以上というのは更に難しい。したがって、少なくとも単体の戦略で週単位、月単位で勝つということはなかなか容易ではないと言える。

逆に言えば、週単位、月単位で勝つためには複数の戦略が必要ということになるだろう。しかし、複数の戦略を用いるにしても、お互いの戦略のパフォーマンスが正の相関であれば、あまり意味がない。しかし、無相関、負の相関の戦略同士を組み合わせるというのは「言うは易く行うは難し」なのである。

だとすれば、週単位、月単位で勝つというのは理想として求めるべきものではある。だが、実際には難しいこととして、週単位、月単位で負けることはよくあること、とゆったりした気持ちで取り組むべきだろう。

OANDA用設定ファイルの作成 (2017/05/10)

OANDA用の設定ファイルを作成する。設定は毎回、コマンド入力してもいいのだが、それでは面倒臭い。そこで毎回使う設定はファイルに記述しておく。

①以下の設定を「settings.ini」ファイルとして「~/py」フォルダーに保存する。

[DEFAULT]
environment = practice
account_id = 1234567
access_token = 1234567890123456789012345678901-2345678901234567890123456789012
fromaddr = abcd@yahoo.co.jp
password = 12345678
toaddr =abcd@example.com
folder_ea = .wine/drive_c/"Program Files (x86)"/"OANDA - MetaTrader"/mql4/Files

②自分の環境に合わせて設定内容を変更し、保存する。

  • environment: 口座の種類を設定するもので、デモ口座の場合は「practice」と入力する。
  • account_id: 「OANDA REST APIの準備」でメモしたアカウントIDを入力する。
  • access_token: 同じく「OANDA REST APIの準備」でメモしたアクセストークンを入力する。
  • fromaddr: 送信元メールアドレスを入力する。戦略のシグナルをメールで送信したい場合、このアドレスで送信する。また、ここではyahooメールを利用することとする。
  • password: 送信元メールアドレスのパスワードを入力する。
  • toaddr: 送信先メールアドレスを入力する。戦略のシグナルをメールで受信したい場合、このアドレスで受信する。これはどこのメールでも構わない。
  • folder_ea: MT4の「Files」フォルダーのパスを入力する。パスはMT4のインストール先によって設定例と違う場合もある。これは戦略のシグナルをEAに送信し、EAで執行したい場合に使う。