2009/11/14

『サヤ』を考える!

今回は、『サヤ』について考えてみました。 まず、はじめに、通貨ペア名について主要通貨をまとめた早見表を作成しました。

見方は、2組の通貨名を選択し、順位を維持したまま組み合わせれば、通貨ペア名になります。 例) AUD + GBP= GBPAUD ※この図の通貨の組み合わせ(ペア)は全28通りとなります。 また、通貨ペア名は、2つの通貨名称と方向を示しています。 USDJPYで見た場合、1USDを売買できるJPY通貨量を示すことになります。 USDJPY:100=100円/ドル(JPY/USD)となります。 ※通貨名と単位は一見逆に見えます。 ここで下図を想定して、JPYにてUSDを売買する場合、2通りの売買方法が考えられます。 ①直接、売買する方法(USDJPY)
②EUR経由で売買する方法(EURJPY ⇒ EURUSD) 実際に下図のデータを元に計算してみると、(条件:初値を使用) ①:USDJPY:90.17(JPY/USD)
②:EURJPY:134.89(JPY/EUR) EURUSD:1.4866(USD/EUR)  
(JPY/EUR)÷(USD/EUR)=(JPY/USD)  134.89  ÷ 1.4866  = 90.737・・・・
③:①と②の差を計算すると   
②90.73- ①90.17 -= 0.56(これがサヤになります。)
経費(スプレッド+スリペect)以上にサヤが広がった場合、ほぼ確実に利益を獲得できます。
上記内容を例にした場合。(条件:共通スプ(3pips)売買共通スリペ(2pips))
①オーダー『USDJPY:BUY EURJPY:SELL EURUSD:BUY』
②サヤが0.05まで縮まったら全決済するとした場合
③結果は、 元サヤ(0.567)- 決済時のサヤ(0.05)- 経費(3×(0.02+0.03+0.02))=利益(0.44) ほぼノーリスクで利益が上がるわけです。 【現実は・・・・・・】 実は、先に使用したチャートは、GMT(世界標準時)からのズレの異なるデータを補正せずに使用したもので、実際のチャートとは異なります。検証時に発覚したミスをそのまま使用してみました。> _<; 1年に一度ぐらいボーナスとしてほしいところですが、実際は、今年1年分のデータで検証すると5分足初値で最大サヤは9pips程度です。 そのため、経費以下となり事実上利用することができません。 しかし、この方法から派生した方法として、類似した通貨を使用する方法があります。この件に関しては後日としておきます。 いかにリスクを下げる方法を見つけるか模索する中で、『サヤ』が重要なキーワードであるような気がします。 2009/1/1~2009/11/13のサヤランキングです。


【余 談】 とうとうMT5(ベータ版)が登場しました。 データ中に出来高が格納できるようになっており(サンプルデータでは、0ですが・・)注目していきたいと思っています。 また、MQL5を見てみると、何やら面倒くさいことになっている様子です。 一般的なことですが、アプリケーションの汎用性を高めると処理が複雑化することが否めません。 多彩な処理が可能になり、処理が高速化される以上仕方がないことです。 また、早くもMQL4からMQL5にコードを変更するスクリプトの作成も行われているようです。 今後、有能なパーツが公開されていけば、MQL4のスキルでMQL5のEA開発が可能になっていくかもしれません。 (気になるソフト)  CHM Editor  MQL5リファレンスなどのヘルプファイルを直接書き換えできるソフトです。しかも、直接Googleなどを利用して翻訳する機能も付いています。しかし、残念なことに日本語との互換性が悪く文字化けしてしまいます。MQL5リファレンスのロシア語から英語への翻訳はこのソフトを使用したのでしょうか?

2009/10/07

基軸を変えると・・・2

先回に引き続き基軸について考えてみました。
まず、基軸として考えられるものとして、
①時間軸(例:一般的なチャート)
②ティック軸(例:ティックチャート)
③価格軸(例:P&Fチャート)
④出来高軸
などが挙げられると思いますが、④は、MT4では取得できません。MT5以降に期待したいところです。
実際に使える軸は、時間①、ティック②、価格③で、扱いやすいデータとなると、①と③になります。
①は、価格軸と時間軸で作られた2次元チャートで、③は、価格軸と価格軸で作られた2次元チャートです。2つを融合すると3次元チャートが作れます。しかし、MT4を使用する利便上で2次元チャートにする必要があります。今回は、『P&Fチャートを時間軸のチャートに表示する』を試みてみました。
【作 成】
一からP&F指標を作成するのも面倒なので、今回は【MQL4Community 内Point & Figure indicator】をベースに使用してみました。下図がその結果です。図の見方は、赤線>青線範囲が、P&F指標で言う上昇バーを示し、赤線<青線範囲が、下降バーを意味しています。つまり、青線が、初値(P&F指標で見た場合)赤線が終値(P&F指標で見た場合)となります。
上図だけでは面白くないので、ボトムライン(水平値)も表示してみました。黄色がボトムラインです。

※今回は、本来のP&F指標の性質を十分に理解して作成したものではありませんのでご了承ください。
【まとめ】
各基軸には、それぞれ特徴・利点が存在します。その利便性を損なうことなく結合出来ればより良い指標を得ることができると考えます。しかし、今回はP&Fの特徴を一部阻害するようなものになってしまったかもしれません。

2009/09/05

基軸を変えると・・・

【はじめに】
為替データの最小単位のチャートは、ティックチャートです。
しかし、このチャートは、時間軸を基軸として作られるチャートではなく、価格が更新されるたびにチャートが作られる価格の更新が基軸となるチャートです。
また、便利上ティックチャートを時間単位にプロットしたものが私たちの使い慣れた時間軸のチャートとなります。
1ティックチャートは、自分で収集するか、有償で手に入れる方法しかなく(もしかしたらあるかも知れませんが・・?)通常、大量のティックデータを手に入れることは難しいことです。
今回は、時間軸のチャート(M1)からティック軸のチャートを作成し特徴をとらえることを試みました。
【考え方】
時間軸からティック軸に変換するために、『1ティックを1秒と考える』と仮定します。
そして、時間軸【M1,M5,M10,M30,H1,H4,D1】のようにティック軸【V30,V60,V100,V200,V500,V1000,V3000】をまとめ、チャートにします。
※1分足を使用することにより、数ティックまとめた価格が抽出できるからです。
【方 法】
MT4に標準装備されている、Period_Converter.mq4を少し改造して基軸変換を行います。
改造したものVp_Converter.mq4を添付しましたので、遊んで見てください。
※動けばOK程度に作っていますので、リアルタイムで使用するコードを削除しています。
Vp_Converter.mq4の使い方
①プログラムの種別  :スクリプト
②パラメーターの説明 :【extern int Vp = 30;】いくつ刻みでティックを纏めるか設定する項目。
③変換方法      :変換するペアのM1チャートを起動させてスクリプトを実行されれば完了です。
④チャートの表示方法 :ファイル(F)→オフラインチャート(O)→変換したペア名Vp,M1というヒストリカルデータができていますので、そのチャートを使用します。
⑤データの相異点   :基軸変換に伴いVolumeの数値を変更していります。変更内容は、ティック数(Volume数)が、刻み数(Vp)を超えた場合の整数倍数を格納するようにしました。
⑥チャートの確認   :以下の画像は、下がVp=600でまとめたチャートで上がH1 のグラフです。



【特徴を捉える】
検証内容を一致させるため、先回のブログ内容と同じ方法を用いグラフ化してみました。下図がそのグラフです。

先回のグラフと見比べてみると、近似したグラフとなりましたが、より1線に纏まったように見えます。
また、近似式は、先回のグラフに使用したものをそのまま使用しました。
【中まとめ】
上記のグラフから、ティック数を基軸したチャートが有効であると考えます。
しかし、実際にリアルタイムで異軸のチャートを使用する際いくつかの問題点があります。
1つは、コンバーターのCPU使用率が高いこと。2つは、時間軸の概念が失われてしまうことです。
このような問題を解決するために、逆転の発想をしてみました。
本来なぜ基軸を変更しなければならないのか?という問題に立ち返ってみると、指標の向上が目的なわけです。
だったら、『指標のみをティック軸にし、それを時間軸のチャートに表示して使用する。』方が利にかなっていると考えました。
【応 用】
ではどのようにするのか?
指標の適用期間を可変しティック軸に合わせれば可能になります。
説明が下手なので適用期間の決定方法を下記にコード添付します。
+―――――――――――――――――――――――――――――――――+
int Get_VP(int i)
{
int ALL = Bars-i-1;
int k,cnt,Vl;
for(k=i,cnt=1;k<=ALL;k++,cnt++)
{
Vl+=Volume[k];
if(Vl>=BaseCount)break;
}
return(cnt);
}
+――――――――――――――――――――――――――――――――+
また、実際にSMAに応用した図も添付しておきます。

このようにすれば、誤差はあるものの『指標のみをティック軸にし、それを時間軸のチャートに表示して使用する。』が可能になります。
【まとめ】
ここまで、ティック軸の有効性を書いてきましたが私自身Volumeに関して悪い記憶があります。
それは、数社を比べた際に倍以上の開きがある場合があったからです。
そのため、各社に対する設定が必要になり、そのためのオリジナルデータの収集が必要になります。
しかし、上記の方法(考え方)は、有効な物と考えています。
例えば、P&F(ポイント アンド フィギア)の考えを取り入れて、異軸を考えてみるのも面白いかもしれません。
また、先に『コンバーターのCPU使用率が高いこと』と書きましたが、スリープを多く取ってやることでCPUの負荷を低減することが可能です。

2009/08/21

フラクタル?呪縛?


先回の投稿で『フラクタル』なる言葉が登場しました。
今回は、フラクタルについて考えるというよりも、為替データを解析していて思わず遭遇してしまったので今回の内容にしました。
まず、『フラクタル』とは、フランスの数学者ブノワ・マンデルブロ (Benoît Mandelbrot) が導入した幾何学の概念。図形の部分と全体が自己相似になっているものなどをいう。(by Wikipedia
為替などの時系列データに置き換えると、いかなる時間足データ間(M1:M5:H1:H4:D1・・・or)を見ても似たような図形、法則が見られることを言う。
で! 今回行った解析が、『値が連続的に増加若しくは減少した、バーの数をカウントして、その出現率を調べる。』です。
【適用内容】
適用通貨ペア:USDJPY
適用範囲  :M1:M5:M30:H1:H4:D1
適用値   :Open[n]-Open[n+1]
プログラム :
+―――――――――――――――――――――+
while(i >= 0)
{
Op = Open[i]-Open[i+1];
Ct=0;
if(Op == 0) Ct = 0;
if(Op > 0) Ct = 1;
if(Op < 0) Ct = -1;
k = Count[i+1];
al = 0;
if(k >= 0 && Ct>=0)al= Ct+k;
if(k > 0 && Ct< 0)al=0;
if(k <= 0 && Ct<=0)al= k+Ct;
if(k < 0 && Ct >0)al=0;
Count[i] = MathAbs (al);
i--;
}
+―――――――――――――――――――――+
【結果】
下図の通り。ただし各データ数にばらつきがあります。
各データ数は、(M1:1000000Bars M5:677716Bars M30:113164Bars H1:56896Bars H4:14747Bars D1:2847Bars)
近似式 出現率=0.435^連続回数 ※0.435は、適当な数値です。
※注意事項:グラフの縦軸は、対数目盛になっています。


【総評】
データ数を考慮に入れると、ほぼ近似するグラフとなりました。これは、『フラクタル』の現象と考えて良いと思われます。
また、出現率が【0.5^連続回数】 を下回ることも新しい発見でした。
【副産物】
今回の解析にあたり、MT4用のスクリプトを作成したので添付しておきます。
スクリプト名 :Export_Indicator_Data.mq4
機能     :指標のデータを為替データと共に、【.CVS】として保存します。(保存先:MT4フォルダ/experts/files)
パラメーター :
extern string IndiMane = " ";指標名
extern int BufIndex = 0;バッファ番号
extern int BarCount = 0;対象バー数(※0なら全データ)
使用方法  :ほかのスクリプトと同じです。
※解析にほかのソフトを利用する場合に便利です。
【まとめ】
フラクタル』とは、面白い現象です。例えば、データを解析するには、多くの信頼のおけるデータが必要です。
これを利用出来れば、ミクロを解析してマクロに生かすことも可能になるかもしれません。
例えば、信頼のおけるミクロデータ(最近のM1データなど)を解析し、H1、H4、1Dで利用するなんて面白いかもしれませんね。
可能かどうかは、まだ分かりませんが今後のプロセスには重要な物になるような気がします。

2009/08/11

『情熱の薔薇』THE BLUE HEARTS が聞こえる!


『♪見てきたことや 聞いたこと いままで覚えた全部 でたらめだったらおもしろい そんな気持ち分かるでしょ!』
昨日から、このワンフレーズが私の頭から離れない。
ことの原因は、【マルチフラクタルを用いた時系列解析 大西立顕】の論文を読んだことから始まった。
『・・・価格差の絶対値は長期相関を持ち、分布は正規分布よりもはるかにすそのの広いベキ分布に従うというような普遍的な統計的特性を持つことが明らかになってきている・・・・・』
『え!ベキ分布って? 普遍的な統計的特性って? 標準偏差はどうなるの?』 
調べてみると。
 



平成20年版国民生活白書 【コラム】正規分布とベキ分布

  【経済物理学 統計物理の目で見る経済現象Ⅰ 高安秀樹】 

 
Coolな経済理論とWarmな金融実務のあいだ~ベキ分布を考える~
ベキ分布―池田信夫blog
上記の内容が見つかった。
※上記を勝手な解釈でまとめてみると
①為替チャートは、統計的フラクタル性(普遍的な統計的特性)を持つこと。
②価格を決定する者(ディーラー)は、数分間(上記論文では2分)の価格差と統計的フラクタル性(普遍的な統計的特性)を元に取引を行っていること。
③価格差の絶対値の分布は、ベキ分布であること。
④価格差の標準偏差の2倍(2σ)内のデータ(全データの約95%)19/20は、ランダムウォークで、残りの約5%(1/20)のデータが、チャートの骨格を成形すること。
⑤お金の非線形【お金は、集まるほど価値が高いので"自然に"集まる性質があること。】
などなど、私の考えを覆す内容がわかってきた。
そして、『♪見てきたことや 聞いたこと いままで覚えた全部 でたらめだったらおもしろい そんな気持ち分かるでしょ!』のフレーズが、頭の中に流れた・・・・『わかるか!!』
【まとめ】
ご存知だった人達から、『今さら何を・・・・』という声が聞こえてきそうだが、私にとって大きな転換点になるだろう。例えば、Mizutoriの概念も修正が必要になし、先回のブログ内容で否定された事項【値幅(価格差)は、値段に比例する】も納得できる。『100年に一度・・・』で片づけていた問題の解決に立ち向かうことができるかもしれない。
【追記】
300年前『それでも地球は回っている!』と言ったガリレオを思いだした。また、自分の無知を発表することになってしまった。

2009/08/06

離散ウェーブレット変換(Haar)


先回のまとめ内に記載したので今回のお題は、データの変換作業の一例としてウェーブレット変換を取り上げてみました。
※ウェーブレット変換で何ができるの?
ウェーブレットには大きく分けると連続ウェーブレットと離散ウェーブレットがあります。
連続ウェーブレット変換
データの周波数の時間的変化を解析することに使用されている。
(はっきり理解できていません・・・・)
参考サイト
短時間フーリエ変換と連続ウェーブレット変換
離散ウェーブレット変換
データの圧縮、ノイズの除去、多重解像度解析に使われている。
参考サイト

   離散ウェーブレット変換 - Wikipedia

http://wwwmp.jwu.ac.jp/mine/SemPPT/2005sem/2005FoundationOfWaveletTransformRevised.pdf
      
今回は、離散ウェーブレット変換の代表であるHaar(以下Haar)を指標化してみました。
※Haarで何をしたいのか?
相場が作る波形を分解し必要な波形を取り出したい。
補足:複雑な波形は、実は単純な波形の組み合わせでできています。
※今回は、Haar理論の説明は省きます。興味がある方は、上記リンクなどを参考にしてください。
下記に添付したファイルにある【DWTHaar.mq4】をもちいて説明します。
選択事項
①波形をどれだけ分割(周波数ごとに)するかを決めます。
【extern int N = 7;】N値が分割数になります。
例)N=3の場合 【高周波数成分中周波数成分低周波数成分】に分割されます。
例)N=5の場合 【高高周波数成分高中周波数成分中周波数成分低中周波数成分低低周波数成分】に分割されます。
※【重要事項】
    N値を上げると細分化が可能になりますが、その際のデータ量が2のN乗必要になり、その分処理能力が落ちてしまいます。
例)N=3の場合のデータ量8:N=5の場合32:N=7の場合128:N=10の場合1024:N=15の場合32768になります。
②どの波形が必要か決定する。
まず、N値最小値に最高周波数成分が対応しN値最大値に最低周波数が対応しています。
【extern int HBs = 3;//高周波カット位置】【extern int LBs = 4;//低周波カット位置】を示しています。ただし、カット位置の数値は含みます。
例)N=3で【HBs=3:LBs=3】の場合【中周波数成分】を出力します。
例)N=5で【HBs=3:LBs=4】の場合【中周波数成分+低中周波数成分】が出力されます。
※一度試してみると分かりやすいと思います。
③その他パラメーター
【Shift = 0】は、検証用のシフトです。シフトしていくと理解しやすいと思います。
※ここまで【DWTHaar.mq4】を試してみると【あれ?】と思うことがあると思います。
今までの指標のように、全期間で指標が表示されません。どうして?
この指標は、あくまでも適用期間(2のN乗)のデータの変換作業を行っているだけだからです。
また、完全に周波数ごとに分解しているのではなく、あいまいに分解していることもわかると思います。
【DWTHaar.mq4】の活用方法
いろいろな活用方法があるかとは思いますが、今回はシンプルな活用方法を提案したいと思います。
【DWTHaar_M.mq4】は、【DWTHaar.mq4】の最新のデータが、期間の平均からどの程度乖離しているかというものです。
※N値を上げた状態で使用すると、(若しくはデータ数が多いと)処理に時間がかかりますので注意してください。
まとめ
今回使用したデータは、初値を使用しています。お好みに応じて変更してください。
また、DWT(離散ウェーブレット変換)は、解析精度を上げると処理能力が、多く必要となります。
それを回避する方法に、高速ウェーブレット変換というものもあるそうです。興味がある方は、検証されてはどうでしょうか?

2009/07/26

Mizutori_EAの指標を検証してみました。


今回の内容は、私が違和感(自分で作っておきながら・・・)を感じていたMizutori_EAの指標について検証してみました。
対象になった指標は、以下のコードの指標です。
+―――――――――――――――――――――――――――――――+
stb = iMA(NULL,0,MaLimtPeriod,MaLimtShift,MODE_SMMA,PRICE_OPEN,0);
HiLimt = High[iHighest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
LowLimt = Low[iLowest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
st = (HiLimt-LowLimt)/(stb/100);
+――――――――――――――――――――――――――――――――+
※この指標を説明すると
ある一定期間(デフォルトなら、80バー期間(約6時間40分))の値幅(終値の高値―安値)を基準値(デフォルトなら、SMMA500)で割り、100倍したものです。
※では、なぜこの指標が必要だったか?(作成した当時の考え方です。)
①ある一定期間の値幅には、ある程度限界があるのではないか?(限界付近での逆張りは、リスク回避につながるのではないか?)
②値幅の限界は、価格に比例するのではないか?(100USDJPY より120USDJPYの方が値幅の限界が大きいはずだ!)
③導き出した値が小さすぎたので100倍して指標とした。
※限界とは,最大の意味ではなく、偏差的発想?ととらえてください。
【作成した当時妙にしっくりくる指標となりまともな検証もしないまま、使用してきました。】
しかし、違和感があったのも事実です。今回は、上記内容を検証してみます。
【検証内容】
手っ取り早く検証するために、今回は、ある一定期間を4時間(つまり4時間足)と設定し、その高値と安値の差を値幅(=高値―安値)として検証してみました。
また、0.01USDJPYピッチで出現頻度(ヒストグラム)を作成しその累計を百分率で表示させました。
下記の図は、2001年~現在までを年ごとにまとめたグラフです。

上記の図を説明すると、縦軸が出現頻度の累計百分率で、横軸が刻み(ピッチ)を表しています。
例えば、2001年では、【0~0.76】の範囲に約90%のデータがあることを意味しています。
また、標準偏差の2倍(95.45%)を値幅の上限(上記で言う限界)と見ると以下の値が導きだされます。
【2001】0.93 【2002】0.88 【2003】0.75 【2004】0.82 【2005】0.70 【2006】0.82 【2007】0.82 【2008】1.35 【2009】1.06(※データ数がほかのに比べて半分程度)
このことが、上記①の内容を意味しています。
しかし、漠然とですが、上記②の内容が否定されていることがわかるでしょうか?
わかりやすくするために、今度は、2001年~現在までのデータを安値を基軸に並べ替えてまとめた物を使用し、上記と同じようなグラフを作りました。
まとめた範囲は、【安値が90USDJPY以下】【90~100】【100~110】【110~112.5】【112.5~115】【115~117.5】【117.5~120】【120~122.5】【122.5~125】【125~】です。

上記図を見て頂くと一目瞭然です。上記指標の考えだと、価格が大きくなれば値幅も大きく(右にラインが移動する)なるはずでした。
しかし、実情は、価格の大きさと値幅は無関係にあることがわかります。
残念ですが、この指標は、不完全な物であるというほかありません。
そのまま使用される場合は、上記②の考えを排除した以下のコードに変更する方がベターだと思います。
+――――――――――――――――――――――――――――――――――――――+
//stb = iMA(NULL,0,MaLimtPeriod,MaLimtShift,MODE_SMMA,PRICE_OPEN,0);削除
HiLimt = High[iHighest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
LowLimt = Low[iLowest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
st = (HiLimt-LowLimt);
+――――――――――――――――――――――――――――――――――――――+
【まとめ】
偶然とは怖いものです。結果ばかり追いかける怖さを再確認しました。
また、上記の図を見て2008年の数値が突出していることが分かると思います。
これが崩壊の原因になったEAも少なくないはずです。
『100年に1度の・・・』との話をよく耳にしましたが、このデータを見ても納得できるところです。
さて、近況報告です。
ここ数カ月Mizutori から距離を置き、資料集めにぼっとしています。特に、データの【変換】方法の勉強です。
今注目している物が、ウェーブレット変換です。もちろん!EAの開発用ですよ!
では!

2009/06/20

自作指標のバグ取り作業


新たに指標を自作した際に付きまとう厄介なバグの修正作業!に注目してみました。
コンパイルは、出来たものの表示されない!MT4が、動かなくなったなど数多く経験されていると思います。
今回は、コンパイル完了後のバグについて記載しておきます。
まず、MT4がフリーズしてしまった時の作業です。
『MT4フリーズ時の脱出方法』
①Windowsタスクマネージャーの呼び出し【XPの場合(CTRL)+(ALT)+(DELETE)】
②(プロセス)→terminal.exeの選択→(プロセスの終了)
③原因の指標の変更
④MT4の起動(再度フリーズの場合は、①に戻る)
A)MT4がフリーズしてしまう場合
①無限ループに陥っている。
※ループ条件の脱出条件が未定の場合に発生します。
よくある?(私がよくする間違い)
例1:
while(i >= 0)
{
************************************
i--;※この条件を忘れてしまう!もしくは、符号を間違える。
}
例2:
For(i=0,k=0;i<100;k++){********************}
※iを終了条件にしているにも関わらず、k++となっており、i++がない場合
※こんなことするわけがないとお思いでしょうが、ループが2重、3重になると意外に多いものです。(私の場合・・・)
除算の分母に0(ゼロ)を代入した場合
※多くは、一端フリーズ状態を経て指標を表示せずMT4が起動して、バーの更新があると最新の指標を表示するなどの症状になります。
※除算の分母に変数を用いる場合は、初期条件に、ゼロを否定する条件を入れたほうが問題の発生を低減させることができます。
例)
Double A =0;
Double B =0;
A = Volume[0];
If(A!=0) B = 10/A;※このようにしておけばゼロエラーが回避できます。
B)指標が表示されない場合(すべては掲示出ませんが・・・)
①基本事項の確認をしてみる
 ・大域での宣言に間違いがないか?(#property indicator_buffers 1 #property indicator_color1 Red など・・・・)
 ※indicator_buffers Xは、表示する指標の個数になっていますか?など
 ・初期関数部(int init())の設定に間違いはないか?(SetIndexStyle(0,DRAW_LINE); SetIndexShift(0,MA_Shift); など・・・・・)
 ※非表示の時系列配列(計算用の時系列配列)も初期関数部でのセットが必要です。
②存在しないものを元に計算処理させた場合
・移動平均を再度平均化処理する場合などに、発生する可能性があります。
C)実際に例を元に、バグ取りを行ってみます。
例)終値を単純移動平均(SMA10)し、再度、単純平均する(SMA10)するコードを以下に示します。
このコードは、コンパイルエラーは起こらず、エラーを含んだコードです。(何個エラーがあるでしょうか?)
//+------------------------------------------------------------------+
1:#property indicator_chart_window
2:#property indicator_buffers 1
3:#property indicator_color1 Gold
4:extern int SMAPeriod = 10;
//---- buffers
5:double SMA[];
6:double SMASMA[];
//| Custom indicator initialization function |
7:int init()
8: {
9: IndicatorBuffers(2);
10: SetIndexStyle(1,DRAW_LINE);
11: SetIndexBuffer(1,SMASMA);
12: SetIndexStyle(2,DRAW_NONE);
13: SetIndexBuffer(2,SMA);
14: return(0);
15: }
//| Custom indicator deinitialization function |
16:int deinit()
17: {
18: return(0);
19 }
//| Custom indicator iteration function |
20:int start()
21: {
22: int CountedBars = IndicatorCounted();
23: int i = Bars-SMAPeriod-1;
24: if(CountedBars>0)i=Bars-CountedBars;
25: while(i >= 0)
26: {
27: SMA[i] = iMA(NULL,0,SMAPeriod,0,MODE_SMA,MODE_CLOSE,i);
28: SMASMA[i] = iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);
29: i++;
30: }
31: return(0);
32: }
//+------------------------------------------------------------------+
※上記コードを用いて、バグ取り手順(素人の自己流なので、ベストな方法か疑問が残りますが・・・・)の説明
①何はともあれ、一度稼働させてみる。
 ※上記コード自体を稼働させないでください。(PCがフリーズします。)
②上記コードを稼働させたところ、PCがフリーズしたため、上記『MT4がフリーズした場合の脱出方法』を元に、脱出し、ループ関数を確認してみる。
A:29:行目【 i++;】が無限ループの原因と発覚!【i--;】 に変更、再度稼働。
B:再稼働後、MT4はフリーズから脱出したが、指標が表示されず。
③1:行目のコードをコメント化【//#property indicator_chart_window】2:行目の上に【#property indicator_separate_window】を記入。
 ※指標をサブウインドウで表示させることで、今後の確認作業を簡素化するためです。(この例ではほとんど関係ありませんが・・・)
④指標表示用配列(上記コードの場合SMASMA[ ]:) にiを代入【28:行目SMASMA[i] = i: //iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);】し再稼働してみる。
 A:この状態で再稼働させても、指標が表示されないため、初期設定を疑う。
 B:初期設定確認時に、10:行目から13:行目にエラーコード発見、下記のように変更。
9: IndicatorBuffers(2);
10: SetIndexStyle(0,DRAW_LINE);
11: SetIndexBuffer(0,SMASMA);
12: SetIndexStyle(1,DRAW_NONE);
13: SetIndexBuffer(1,SMA);
 ※ちなみに、【SetIndexBuffer(A,B)】とは、配列(名前B[ ])をバーが更新するたびに、更新してくれる機能(バッファ)を持たせるというものです。
  例)【B[0] =5 B[1]=4 B[2]=3】の場合、新規バーが発生すると、【B[0] =新規 B[1] =5 B[2] =4 B[3] =3】になります。
  また、SetIndexBuffer(バッファ)の設定は、8つまで持つことができます。Aは、その番号です。(ただし、A=0~7です。)
  番号の割り当ては、0から始めなければならないお約束があります。
  つまり、元のコード(エラーコード)を訳すと!
   9行目 2つのバッファを設定します。
  10行目 バッファ1は、線表記を設定 (本来は、バッファ0にセットしなければなりません。)
11行目 バッファ1に配列名SMASMAをセット(本来は、バッファ0にセットしなければなりません。)
  12行目 バッファ2は、表記しません。(本来は、バッファ1にセットしなければなりません。)
13行目 バッファ2に配列名SMAをセット(本来は、バッファ1にセットしなければなりません。)
  こんな感じです。
  つまり、ここでエラーが発生していたことになります。
 C:再稼働後、右肩下がりの指標が現れる。④で変更したコードを元に戻す。【28:行目SMASMA[i] =iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);】コンパイル後再稼働
 D:再度指標が表示されなくなる。
⑤前処理用の配列(バッファ)【SMA[ ]】が機能しているか確認してみる。コード変更【28:行目SMASMA[i] = SMA[i] ; //iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);】
  A:コンパイル後、再稼働!指標が表示されていることを確認
  B:上記記載『B)② 存在しない配列を元に計算処理させた場合』が考えられるので、ループを別にしてみる。
int start()
{
int k;(新規ループ用に追加)
int CountedBars = IndicatorCounted();
int i = Bars-SMAPeriod-1;
k = i-SMAPeriod; (新規ループ用に追加)
if(CountedBars>0){i=Bars-CountedBars-SMAPeriod;k=i;} (新規ループ用に追加)
while(i >= 0)
{
SMA[i]=iMA(NULL,0,SMAPeriod,0,MODE_SMA,MODE_CLOSE,i);
i--;
}
while(k >= 0)
{
SMASMA[k] =iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,k);
k--;
}
return(0);
}
⑥コンパイル後再稼働で指標が表示された。③で変更した部分を元に戻し終了です。(バグ取り完了)お疲れさまでした!
D)作成した指標が予定通り稼働しているか確認する。
 ※これが一番厄介なことです。なぜなら、実際のデータで指標を動かしても、自分の考え通りなのか不明確であることが多いためです。
 そのため、サンプルデータを用いて確認する方法があります。
 添付ファイルは、適当に作ったサンプルデータ(日足用)です。不要なシンボルに組み込んでみてください。
 以下のようなチャートが現れるはずです。(わかっているとは思いますが、指標は別です。)

ご参考までに!
追記
『今年中にMT5が発表予定!』とか、『金融庁によるレバ規制!』とか、今後目まぐるしく変化することと思います。
やなぎのごとく柔軟に対応できるチカラ!を持ちたいものです!では・・・

2009/05/27

移動平均線ってなに?

先回の掲示に不適切な部分がありましたので、訂正し掲示しておきます。
『今さら何を!』との声が聞こえてきそうですが、『初心者向け』というよりは、私自身が無知だったので私の学習も兼ねて作成しました。

【移動平均線の特徴】
①そのまま記載すれば、適用期間の平均を適用期間の最新の値の位置に記載したもの。
②平均の取り方には、数多くの方法が存在する。(MT4の標準は4種類)
③移動平均線の適用期間が長くなると、データの平滑化が進む。
④データを多周波数の集まりと見ると、移動平均線とは、低周波通過フィルタとして機能している。
⑤移動平均線の最大のデメリットは、遅延である。

【移動平均線の書き方】
時系列データが、左から右に行くに従い新しいデータになる場合、適用期間の一番右(最新のデータ位置)に記載するのが基本です。また、最新のデータ位置よりも右(未来のデータ位置)にシフトして使われる場合もあります。例)Mizutori_EAの旧エンジンに使用していたSMA(単純移動平均線)は、最新のデータ位置に5バー過去のSMAをシフトして使用しています。つまり、最新のデータ位置のSMAデータは、5バー先の未来のデータの判断に使用しています。また、一目均衡表の遅行スパンのように左にシフトする場合もあります。

【移動平均線の種類】
  MT4に標準で装備されているものだけで4種類存在します。
①単純移動平均(SMA)
SMA=(適用期間のデータの合計)/(適用期間)
②線形加重移動平均(LWMA)
LWMA=(D[0]×(W-0) + D[1]×(W-1) + D[2]×(W-2)…….. +D[n-1]×(W-n-1)+D[n]×(W-n))/(加重合計)
※D[n]:データ(D[0]が最新、D[n]が最後)
※(W-n):加重 (W-n)=1 :(W-n-1)=2
例)適用期間:4 データ{9:8:7:6}(右が最新)の場合
LWMA =(6×4+7×3+8×2+9×1)/10= 7
③指数移動平均線(EMA)  A=2/(適用期間+1)※A<1
EMA=A×D[0]+(1-A)×EMA[1]
※D[0]:適用範囲の最新データ
※EMA[1]:1つ前のEMA値
④平滑移動平均線(SMMA)
SMMA=(D[0]+SMMA[1]×(適用期間―1))/適用期間
※D[0]:適用範囲の最新データ
※SMMA[1]:1つ前のSMMA値 ◆そのほかにも無数に存在します。たとえば、LWMAの加重をフィボナッチにするとか!EMAのAを変更するとか!しかし、大きく分類すると2種類になります。①と②のように適用期間内で計算処理が完了するものと、③と④のように前回の結果をもとに処理されるものに分類できます。また、③④は、適用期間以上にデータがないと(十分に過去のデータがないと)、軽微な誤差を伴います。 ちなみに、④のSMMAを③のEMAの公式の形にすると! ≪A=1/適用期間: SMMA=A×D[0]+(1-A)×SMMA[1]≫ となります。つまりAの初期条件を変えたものです。 また、A=3/(適用期間+2)にすると・・・・・・後ほど説明します。

【移動平均線の役割】
【SMA】 図1は、元データに波長(λ)20のSIN曲線を用い、適用期間を5(λ/4),10(2λ/4),15(3λ/4),20(λ)にしたSMA(単純移動平均線)です。振幅が徐々に減り、SMA(20)の時に振幅が0になります。また、期間が長くなればなるほど、振幅の頂点は、右にズレていきます。ただし、波長が変わることはありません。 図2は、元データに波長(λ)20のSIN曲線を用い縦軸に振幅の最大値、横軸にSMAの適用期間を示した図です。まるで高い位置からボールを落とした時の軌跡のようです。これは、SMAの適用期間の違いによりどれだけ元データが減衰されたかを示しています。SMA(20)で一時、振幅が0になり再度、振幅が現れますが、その振幅は、元データの30%程度です。そして、再度0になり再再度、振幅が発生しますが、初回の振幅の減衰に比べて減衰量が減ります。その後、振幅の最大値は、微量に減っていきますが、0になることはありません。また、適用期間20(λ)の整数倍で振幅=0が繰り返されます。この図でわかることは、逆転の発想で、SMAの適用期間の3/4より短い波長は、SMAすることにより、著しく減衰され、適用期間より長い波長は、多少の減衰はあるものの、残る(通過する)ことがわかります。つまり低周波通過フィルタの役割をしています。

【EMA】 図3は、図1のデータをEMAに置き換えたものです。EMAの特徴として、振幅が0になることはありません。 また、適用期間ごとの振幅の頂点のズレ(遅延)がSMAより少ない。しかも適用期間を大きくした場合のズレ(遅延)の間隔が少なくなっていくのがわかります。 図4は、図2のSMAをEMAに置き換えたものです。元データの70%程度減衰する適用期間が20となっています。SMAのように記載すると、EMAの適用期間より短い波長は、EMAすることにより著しく減衰されます。しかし、適用期間より長い波長でも、SMAと比べた場合、減衰量が多いのが特徴です。つまりSMAより精度が劣る低周波通過フィルタの役割をしています。


【その他】
図4は、縦軸をY:横軸をXとした場合のY=X+1の直線を元のデータとした場合のズレ(遅延)を図形化したものです。縦軸がズレ(遅延)量:横軸を適用期間としています。凡例が4種類あるにも関わらず、3本しか線がありません。これは、SMAとEMAが同じ値をとり重なっているのが原因です。言い換えれば、MT4に標準装備されているEMAは、Y=X+1の直線時のズレ(遅延)がSMAと同じ値をとるように調整された、指数移動平均線でることを示しています。また、EMAの変数AをA=3/(適用期間+2)とした場合、LWMA(線形加重移動平均)と同じ値となります。  


【まとめ】
  何気なく使用してきた移動平均線ですが、調べてみると奥が深く完全に理解することができませんでした。 しかし、今後のEA作成には、役立と思っています。また、トレードに理想的な移動平均線とは、遅延が少なく平滑な平均線であると思っています。  

【参考文献】
ロケット工学投資法 ジョン・F・エーラース 著 

2009/04/17

Mizutoriをカスタマイズ!


ご無沙汰しております。
今回の課題は、『なぜこのEAの取引数が、サーバー(取引業者)によって異なるか?』です。
※この内容は、私の憶測です。

大きく分けると4つの要因が考えられます。
①サーバー(取引業者)によって微妙にデータが違い、それが原因となり注文処理が行われずスルーするのではないか?
②サーバー(取引業者)との接続状況もしくはサーバーの処理状況が悪く、本来1Pips毎に送られてくるデータが数Pipsまとめて送られてくる場合に注文処理がスルーするのではないか?
③こちらからは、注文オーダーを出したにも関わらず、サーバー(取引業者)で受け付けてもらえなかったからではないか?(この要因は、今回対象外としておきます。)
※ちなみに『OFF QUOTES エラーについて by FXDD
④PCの処理途中にpipsの更新があり、対応できない場合に注文処理がスルーするのではないか?(この要因は、今回対象外としておきます。)

2つの要因に対する解決策(?)は?
①に対しては、オリジナルのデータを元に、パラメーターの調整をすることで対応する方法がベターかもしれません。
②を今回のテーマと位置づけて考えてみました。
A)まずこのEAの取引条件の要の2つの条件を考えてみます。
1.『上部の乖離線を売値が越えたら売り!』若しくは、『下部の乖離線を買値が下回ったら買い!』としています。
 2.上記かつ、『RSI【(期間14)終値】が(ある数値を越えたら売りorある数値を下回ったら買い)としています。
※つまり、データがまとめて配信され、その中の一部のデータが、取引条件を超えていても
まとめられたデータの最後の値が、取引条件に達していなければ取引は成立しません。
これが、接続状況及びサーバー処理状況による取引回数が減る要因だと考えました。
B)上記の対策として、以下のように取引条件を変更してみました。
1.『上部の乖離線を現在のバーの高値が越えたら売り!』若しくは、『下部の乖離線を現在のバーの安値が下回ったら買い!』
 2.上記かつ、『RSI【(期間14)終値「ただし、現在のバーのみ高値or安値」】が(ある数値を越えたら売りorある数値を下回ったら買い)
C)上記の内容にしたらどうなるか?
利点:『新しいバーが作成されるか、または、注文オーダーが通るまで注文シグナルを送り続けます。』
欠点:『注文は処理されたが、予定値と実際の注文値に開きが生じる可能性がある。』

では、どの様に実装すればよいか?を以下に掲示しておきます。
①まず、『MQL4からRSIの指標を入手し指標のフォルダーに格納』 iRSIの代わりに使用します。
②次に、EAを開き以下のコードを追加する。
【指標の計算の変更(RSI期間14の場合)】
//RSI = iRSI(NULL,0,14,PRICE_CLOSE,0); 『要らないコードの削除もしくはコメント化』
double Hi_RSI;
double Lw_RSI;
double sump=0,sumn=0,rel=0;
double positive=0;
double negative=0;
double B_positive = iCustom(NULL,0,"RSI",1,1);
double B_negative = iCustom(NULL,0,"RSI",2,1);
//Hi_RSI用
rel=High[0]-Close[1];
if(rel>0) sump=rel;
else sumn=-rel;
positive=(B_positive*13+sump)/14;
negative=(B_negative*13+sumn)/14;
if(negative==0.0) Hi_RSI=0.0;
else Hi_RSI=100.0-100.0/(1+positive/negative);
//Lw_RSI用
sump=0;sumn=0;
rel=Low[0]-Close[1];
if(rel>0) sump=rel;
else sumn=-rel;
positive=(B_positive*13+sump)/14;
negative=(B_negative*13+sumn)/14;
if(negative==0.0) Lw_RSI=0.0;
else Lw_RSI=100.0-100.0/(1+positive/negative);
【条件式記入場所】(参考)
(BUY)
if(
(!OderStop)
&&(pos1<Max_Position)
&&(st>=Xox)
&&(Lw_RSI<=RSILowLimt)【RSIをLw_RSIに変更】
&&(MaLow>=Low[0]) 【AskをLow[0]に変更】
&&(ATR<=ATRLimt)
&&((Ask<=(LastPrice-(PipStep*Point)))||pos1==0)【お好みで、ASKをLow[0]に変更】
)Buy_Flag = true;

(SELL)
if(
(!OderStop)
&&(pos2<Max_Position)
&&(st>=Xox)
&&(Hi_RSI>=RSIHiLimt)【RSIをHi_RSIに変更】
&&(ATR<=ATRLimt)
&&(MaHi<=High[0]) 【BidをHigh[0]に変更】
&&((Bid>=(LastPrice+(PipStep*Point)))||pos2==0)【お好みでBidをHigh[0]に変更】
)Sell_Flag = true;

こんな感じになります。

まとめ
本来は、フォームに掲載するような内容ですが、ブログの更新のために使用させて頂きました。
また、お決まりのように、フォワードテスト等をしておりませんので、ご使用される方は、『人柱覚悟!』でお願いします。
では!

2009/03/07

バックテストの高速化


EA作りは、何度もバックテスト(検証)作業をしながら作り上げていくものです。
しかし、その検証に時間を費やされることは非常に苦痛です。
今回は、少しでも検証スピードを上げる方法(バックテストの高速化)を提案しておきます。
※なぜEAごとに検証スピードが異なるか?
簡単に言ってしまえば、処理容量が多いとスピードが落ちてしまうからです。
しかし、多くのEA(検証スピードのおそいEA)は、無駄な処理(必要のない処理)が含まれています。
処理作業を遅らせる要因は?
①大量のループ作業
例)100回ループがEA内にあり何も対策をしていない場合
データ分処理するとすれば、100回ループ×4回(1M[初値・高値・安値・終値])×検証時間軸(1Hなら×60)×検証期間となります。
②外部(EA外)の指標(インジケーター)の利用
※表示用に無駄な作業が含まれるため、処理スピード低下の要因となります。
※それらを回避するための対策は?
①大量のループ作業がある場合
A)時間軸の初値でオーダーの取引を検討するEAの場合
※【if(Volume[0]>1||!IsTradeAllowed())return(0);】をint start() { の後に追加しておく。(初値で処理をするという意味です。)
B)A以外のEA
※for(int i=0;i<Limit;i++)をfor(int i=0;i<Limit;i=i+10)のように変更してループ回数を減らしてみる。
※ただし、内容が粗悪になるため注意が必要です。(以外に使えます。)
②外部(EA外)の指標(インジケーター)の利用の場合
※簡単に言ってしまえば、必要な処理だけをEAの中に組み込んでしまえばそれが対策となります。
※しかし、フォワードテストやリアルで使用する際に、表示用として指標を表示させると2重処理していることになるのでPCへの負担は増えます。
例として、VQという指標をEA化したものを添付しておきますので確認してみてください。

まとめ
検討結果が、すぐにわかるのがEA作りの面白いところです。

2009/02/19

Mizutori_EAの賞味期限


このEAの賞味期限を検討してみました。
対象バージョン:Mizutori20.1_Custom_EA(デフォルト)
使用データ:MQ(2006/1~2009/1)※問題はありますが検証用ということで。
添付グラフの説明:月別に取引回数と利益をまとめてみました。


参考資料:VIX指標(恐怖指数)http://chartpark.com/vix.html
参考資料(VIX指標5年)とグラフを見比べて頂くと類似しているような気がしませんか?
前々から気になっていたことですが、この指標を利用すればある程度このEAの賞味期限がわかってくると思っています。


例えば、VIX30以下になると、極端に取引回数が減少しそれに伴い利益も思うように上げることができなくなってきます。
それが、このEA(20.1)の賞味期限ではないでしょうか?
では、どうすればいいのでしょうか?
パラメータを変更して、取引回数を増やす?
たぶん得策ではありません。
私の考えでは、それを補うための新たなポジション取得条件の追加が必要だと考えています。
そのため、最近のバージョンは、新条件を追加したものが多数存在します。
また、新条件毎のPfの設定もできると面白いかもしれませんね。
もうひとつの賞味期限が、先に訪れるかもしれませんが・・・・・・
ご参考までに・・・・
追記
VIX指数が上限に近づくとどのような動きになるか?という質問がありましたので。
※この内容は、私の予測です。
まず、VIX指数とは、
将来の投資家心理を示す数値として利用されており、英語で「investor fear gauge」、日本語で「恐怖指数」という別名が付けられています。
VIX指数は、通常時10~20の範囲内動き、相場の先行きに不安が生じた時に数値が大きく上昇する特徴があります。 だそうです。 これから予測すると、 ①相場の先行きに不安があれば、投資家は、資金を引き揚げる。 ②引き揚げた資金を違う市場で運用する。(少なからず為替市場にも流れているはず。※市場の出来高がわかればある程度裏付けが取れるかもしれませんが、そのような立場にはいませんので確認が取れません。) ③市場での運用されている方のシステムは、ボラが大きくなれば利益が多くなるシステムだと聞いたことがあります。(順張のシステム?)資金量が増えれば行き過ぎた相場になる。これをウサギだとすると。 ④それを捕食するオオカミが増える。(荒れた相場では、乖離が有効とされているそうです。) ⑤VIXの数値が下がれば、資金が戻る。 ⑥ウサギの餌(資金)が減れば、ウサギも減りオオカミも減る。 ⑦オオカミが減れば、このEAの成績が下がる。 と予測しています。 つまり、このEAは、オオカミ的な要素のEAだと思っています。 ご参考までに・・・・・・

2009/02/13

Mizutori_EAのパラメーターの説明


いろいろなバージョンを作ってしまったので、今回は、25.4を基本に説明します。
共通事項
各パラメータに適用する価格は、極力初値(PRICE_OPEN)を使用しています。
理由は、バックテストした時の誤作動を防止するためです。
終値(PRICE_CLOSE)は、そのバーが確定するまで更新される値です。最新の決定された数値を得ようとすると、初値となります。
トレンドフィルター
double MaSS = iMA(NULL,0,25,0,MODE_EMA,PRICE_OPEN,0);
double MaSM = iMA(NULL,0,50,0,MODE_EMA,PRICE_OPEN,0);
double MaMS = iMA(NULL,0,100,0,MODE_EMA,PRICE_OPEN,0);
double MaMM = iMA(NULL,0,200,0,MODE_EMA,PRICE_OPEN,0);
double MaLM = iMA(NULL,0,300,0,MODE_EMA,PRICE_OPEN,0);
double MaLL = iMA(NULL,0,400,0,MODE_EMA,PRICE_OPEN,0);
上記6つの指数平滑平均線(EMA)を用いてトレンドの発生を監視しています。
各平均線がクロスすることなく、虹状態になった場合に『トレンドが発生した!』としています。
問題点
※『ダマシ』に弱いため、初期でフィルターが効かないことがある。
※『トレンドが発生していない(トレンドが消えた)部分を含んでしまう。』
メインエンジン
double Ma = iMA(NULL,0,MaPeriod,MaShift,MODE_SMA,PRICE_OPEN,0);
double Bands_Ma = iMA(NULL,0,10,0,MODE_SMA,PRICE_OPEN,0);
double Bands = Bands_Ma*(Percent/100);
double MaHi = Ma+Bands;
double MaLow = Ma-Bands;
上記の5つのコードでメインエンジンを構成している。
Maが軸となる移動平均線でデフォルト状態だと、期間5シフトをした期間10の単純移動平均線(SMA)。
Bands_Maは、バンドの巾を形成するための数値を得るための、期間0シフトの期間10の単純移動平均線(SMA)。
Bandsは、Bands_Maを用いて幅を形成しています。
MaHi・MaLowは、Maを軸にした上下の巾を形成したものです。
問題点
※Percentを固定しているため、極端な値動き、値動きが少ない時などの分別が付かない。また、USDJPYM5に特化した数値のため他の通貨ペアに対応しづらい。
サブエンジン
double MaHi_Tr = Ma*(1+Percent_Tr/100);
double MaLow_Tr = Ma*(1-Percent_Tr/100);
メインエンジンに同じ。ただし、使用目的に合わせるために、Percentをメインエンジンと異なる仕様にできるようにしてあります。
期間内の高値と安値の抽出
double HiLimt = High[iHighest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
double LowLimt = Low[iLowest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
LimtPeriod期間内の最も高い(低い)終値がついたバーの高値(安値)をHiLimt/LowLimtに格納
※敗戦処理及びXoxの計算に使用します。
期間内の最高値(最安値)を使用しない理由は、極度に長い髭(瞬間的に付けた値)を回避するためです。
問題点
現在のところ、特にありません。
その他のパラメーター
double RSI = iRSI(NULL,0,14,PRICE_CLOSE,0);
※終値を利用した、期間14のRSI(Relative Strength Index)(相対力指数)

double Dv = iStdDev(NULL,PERIOD_H4,Dv_Period,0,MODE_EMA,PRICE_CLOSE,0);
※終値を利用した、4時間足での標準偏差で、グローバルに値が動いた時のフィルターとして使用しています。
double ATR = iATR(NULL,0,ATRPeriod,0);
※突発的な値動きがあった時のフィルターとして使用しています。
問題点
以下のようなコードの指標のため、バックテストでフィルターが作用し、リアルでは効かない可能性があります。
※ATR (Average True Range)の内部コード
double high=High[i];
double low =Low[i];
double prevclose=Close[i+1];
TempBuffer[i]=MathMax(high,prevclose)-MathMin(low,prevclose)
【高値[0]と終値[1]の高い方から安値[0]と終値の低い方を引いた数値をTempBufferに格納
AtrBuffer[i]=iMAOnArray(TempBuffer,Bars,AtrPeriod,0,MODE_SMA,i);
【TempBufferの期間(デフォルトなら2)の平均がATRの数値となります。】
double stb = iMA(NULL,0,MaLimtPeriod,MaLimtShift,MODE_SMMA,PRICE_OPEN,0);
double st=(HiLimt-LowLimt)/(stb/100);⇒100×((HiLimt-LowLimt)/stb )と置き換えます。
※変動係数(本来は、標準偏差/平均値を意味します。)を求め変動係数が小さい時は、内部エネルギーが蓄積されたと判定し、トレードを制限するために使用します。
※stbは、期間(デフォルト500)の平滑移動平均線で、軸となる価格を抽出するために使用しています。
※stは、高低差を軸となる価格で割ったものを100倍した【変動係数】を格納するものです。
参考
下記の式が上記式に近似します。(添付Bora指標参照:青が下記の指標、白が上記指標です。)
double st=MathLog(HiLimt/LowLimt)*100;
※たぶん、logを使用した方が、本来の意味に近づくと思っています。(USDJPYでは、(HiLimt-LowLimt)/(stb/100)がフィットしています。)
ちなみに LogA=e^Aです。
まとめ
大きなトレンドを避けて、逆張りを行っていけばある程度の成績が可能になると思います。
また、追加もしくは削除しなければならない指標があることでしょう。
フィルターを締め付けると、ほとんど取引をしなくなり、緩めると大きな損益が発生しますので注意してください。
それでは・・・。

2009/02/11

成長曲線


オカミとウサギの話をした時のことを覚えていますか?
その中で、オオカミが0の場合ウサギの個体数は、どうなったでしょうか?
その時のグラフだと、無限に個体数を増やしていました。
自然界では、ありえませんね。
例えば、ウサギが食べる餌の量や、敷地に制限があり無限に個体数を増やすことは考えられません。
そこで、自然界をモデル化した公式があります。
代表的な物が、ゴンペルツ曲線とロジスティック曲線です。

ゴンペルツ関数
Y=a×b^EXP(-c×X)
※a=限界数:b=変数:-c=変数:EXP(J)=e(ネイピア数)のJ乗を意味する。
ロジスティック曲線
Y=a/(1+b×EXP(-c×X))
※a=限界数:b=変数:-c=変数:EXP(J)=e(ネイピア数)のJ乗を意味する。
添付したグラフは、系列1がゴンペルツ関数(a=100:b=0.1:c=1)で系列2がロジスティック関数(a=100:b=1:c=1)です。
2つの違い(特徴)は、ロジスティック関数が、変曲点に対し左右対称の曲線になるのに対し、ゴンペルツ関数は、非対称となることです。
成長曲線は、生物の個体数、プログラムのバグ累計数、販売累計台数などのモデルとして用いられているそうです。
ご参考までに。

2009/02/08

為替データ(USDJPY)

※ここに記載する内容は、私の思いこみで書かれています。
他の裏付けが取れている内容ではありません。

ヒストグラムを作成してみました。
ヒストグラムとは、データの分布状況を視覚的に認識するため作られたグラフのことです。

データの説明
ティック数1440以上とは、1分間に1回以上行われたデータつまり、1日分のデータがあると思われるデータのみ抽出しました。
データ区間のマイナス領域は、下げ日であった日、プラス領域は、上げ日であった日を表します。
また、横軸の数値が、区間(@0.1)を示し、縦軸がその区間に入るデータの数を示しています。
次のヒストグラムは、系列1が日足、系列2が4時間足、系列3が1時間足を示しています。
縦軸は、そのデータ区間が全体の区間に占める割合をパーセントで示しています。
これらのグラフからわかること
①ほぼ左右対称になっていることから、上げも下げも同様な変化量を持って変化していることが分かる。
②日足でみた場合、終値-初値の値が-2.5から2.5間に99.5% -2.0から2.0間で98.7% -1.5から1.5間で96.5% -1.0から1.0間88.9%のデータが入る。(グラフと元のデータより)
4時間足の場合、終値-初値の値が-1.0/1.0間99.1% -0.5/0.5間93.1% -0.3/0.3間82.3%
1時間足の場合、終値-初値の値が-0.3/0.3間96.0%
今回は、グローバルな視点でデータを検証してみたが、新しい発見ができませんでした。
今後、暇を見て、下記の検証をしてみようと思います。
ここからは、私の勝手な仮説です。
①『値は、動きたがっているようだ!』
値は、絶えず動きたがっていて、その理由を探している。何らかの要因で、その動きが止められた時その力は、蓄積される。
そして、その原因が、解決された時、蓄積された力は、放出される。
②『値動きは、指数関数的な動きをしそうだ!』
絶えず一定の割合で動くのではなく、成長曲線的な(ゴンペルツ曲線や、ロジスティック曲線)動きを見せることが多い。
③『どうも、値動きの激しい時間帯とそうでない時間帯がありそうだ』
たとえば、大きく分けて、アジアが中心となる時間帯とEUが中心となる時間帯とUSAが中心となる時間帯があり、その市場ごとで、値動きに違いがありそうだ。
また、1週間を通して急激なトレンドが発生した場合に週末に戻しが入ることが多そうだ。

2009/02/05

コピペでエラーが・・・


よく聞く話しですが、何を言っているのかわかりませんでした。
よく聞いてみると、サイトなどに書いてあるコードをそのままコピペしてEAに張り付けても動かないとのことです。
自分でやってみて納得しました。
原因は、全角スペースです。
コピペする際に、半角スペースで書かれているものが、全角スペースになるようです。
対策として、貼り付けた部分を、矢印キーでカーソル移動してみてください。問題の個所(全角スペース)の部分に【 @ 】が現れます。
それを削除すれば、対策終了です。
ご参考までに・・・

2009/02/04

Mizutori_EAの説明(カスタムユーザー向け①)


表示にバグがありましたので修正しました。
Mizutori_EAの内部で何を行っているか、順に説明していきます。
本職の方が見たら、ホントでそれでいいのか?と問いかけたくなるところがあると思います。気になりましたコメントください。)
では、初期化関数から見ていきます。
この初期化関数『init()』は、EAを作動した時に1度だけ作動する場所です。
 一度だけ処理すれば、解決する内容を記載します。
int init()
{①
マジックナンバーの取得
Mc1Number = MYMAGIC + MagicfromSymbol();
【MagicfromSymbol()関数で処理した数値にMYMAGICを加えMc1Number(大域変数)に格納する。】
Profitの確認
TPf = Take_Profit();
【Take_Profit()関数で処理した数値をTPf(大域変数)に格納する。】
return(0);
}①
後処理関数です。(省略可能)
int deinit()
{
return(0);
}

ティックが更新するたびにスタート関数『start()』が呼び出されます。
expert start function
int start() {
int Order = SIGNAL_NONE;
int pos1=0,pos2=0;
bool OderStop = false;
bool OderClose = false;
bool fbp = false;
bool fsp = false;
//double Profit =0;
int Now_Time = TimeCurrent();
【現在のサーバータイムをNow_Timeに格納】
//int NowDay = TimeDay(Now_Time);
int NowHour = TimeHour(Now_Time);
【現在のサーバータイムを時間軸(時)に変更し、NowHourに格納】
int NowMin = TimeMinute(Now_Time);
【現在のサーバータイムを時間軸(分)に変更して、NowMinに格納】
if(!IsTradeAllowed())return(0);
【もし取引が可能でなければ、start()関数終了】
オーダーの凍結
int NT,FrT,ExT;
if(Trade_Freeze)【もしTrade_Freezeが真(true)なら{から}までを実行する。】
{①
NT = (60*NowHour)+NowMin;
【(60*NowHour)+NowMin『現在のサーバータイム』をNTに格納】
 ※●分を×分に変換しています。
FrT = (60*Freeze_SH)+Freeze_SM;
【設定したオーダー凍結開始時間を分に変換してFrTに格納】
ExT = (60*Freeze_EH)+Freeze_EM;
【設定したオーダー凍結終了時間を分に変換してExTに格納】
if((FrT<ExT)&&(FrT<NT)&&(NT<ExT))OderStop = true;
【もし( )内の条件が真(true)ならOderStop に真を格納】
if((FrT>ExT)&&((FrT<NT)||(NT<ExT)))OderStop = true;
もし( )内の条件が真(true)ならOderStop に真を格納】
}①

週末制限 および制限
if(Weekend_Stop==true && DayOfWeek()== Stop_Day_Of_Week && NowHour>=Stop_Hours)OderStop = true;//週末のオーダーストップ
 【もし( )内の条件が真(true)ならOderStop に真を格納】DayOfWeek()は、現在のサーバータイムの曜日(日~土)を0から6の数値で表す関数です。
if(Weekend_Stop==true && DayOfWeek()>Stop_Day_Of_Week)OderStop = true;
 【もし( )内の条件が真(true)ならOderStop に真を格納】
if(Weekend_Close==true && DayOfWeek()==Close_Day_Of_Week && NowHour>=Close_Hours)OderClose = true;//週末のオーダー強制決済
 【もし( )内の条件が真(true)ならOderClose に真を格納】
if(Weekend_Close==true && DayOfWeek()>Close_Day_Of_Week)OderStop = true;
 【もし( )内の条件が真(true)ならOderStop に真を格納】

最後に決済したオーダーの抽出
1時間の間最後に決済されてから金額よりも悪い条件で取引することを防止するための仕様です。
 int ht = OrdersHistoryTotal( )-1;
 【過去のオーダー数 -1をhtに格納】
int ODT = 0;
for(int Z = ht ; Z>=0 ;Z--)
 【過去のオーダー数回{~}内を繰り返す。Zは、過去のオーダー数からの引き算】
 過去のオーダーは、古いものから新しいもの(最後に決済したもの)の順に並んでいます。一番古いもの・・・・・・・・・・一番新しいもの
{
if(OrderSelect(Z, SELECT_BY_POS, MODE_HISTORY) == true)//口座履歴の選択
  【もし過去のデータファイルからデータを抜き出せたら{~}内を処理する。】
{
if(OrderMagicNumber() != Mc1Number) continue;//マジックナンバー
【もしマジックナンバーが異なっていたらこの処理をスキップする。】
datetime HistoryLastTime = OrderCloseTime( ) ;//決済した時間
【決済した時間をHistoryLastTimeに格納する。】
double HistoryLastPrice = OrderOpenPrice( ) ;
 【注文した時の価格をHistoryLastPriceに格納】
ODT = ODT+1;
 【ODTに1を加える】
}
if(HistoryLastPrice>0)break;
 【HistoryLastPriceが0以上ならループから脱出する。】
 }
 //ポジション取得の許可
int now =TimeHour(Now_Time-HistoryLastTime) ;
 【現在の時間から最後に決済された時間を引いてnowに時間単位(時)で格納】
if((now>=1)||(ODT==0)||(Ask<=(HistoryLastPrice-(PipStep*Point))))fbp = true;
 【もし(最後に決済されてから1時間以上経過した)または(過去のオーダーがない)または(最後に決済した価格よりもASKが下回ったら)fbpに真を格納する。】
if((now>=1)||(ODT==0)||(Bid>=(HistoryLastPrice+(PipStep*Point))))fsp = true;//
 【もし(最後に決済されてから1時間以上経過した)または(過去のオーダーがない)または(最後に決済した価格よりもBidが上回ったら)fbpに真を格納する。】
if(!Sort_Order){fbp = true;fsp = true;}
 【もしSort_Orderが真でなければ{ }を処理】
オープンポジションの抽出
//ポジション数の確認およびラストオーダーの金額の抽出
ポジションは、古いオーダー・・・・新しいオーダーの順で格納されています。
double LastPrice = 0;
for(int i=0;i<OrdersTotal();i++)【注文分繰り返す】
{①
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true){② //注文ポジションの選択
【もしデータファイルからデータを抜き出せたら{~}内を処理する。】
if(OrderMagicNumber() != Mc1Number) continue;//マジックナンバー
【マジックナンバーが異なればスキップ】
if(OrderType()==OP_BUY)pos1++;
 【BUY注文があればpos1に1を追加する】
if(OrderType()==OP_SELL)pos2++;
 【SELL注文があればpos2に1を追加する】
LastPrice=OrderOpenPrice();
【約定金額をLastPriceに格納】
}②
}①
int posX = pos1+pos2;
if((posX==0)||(posX > NumPos))
【もし( )内の条件のどちらかが真から{①}内を繰り返す。】
{①
NumPos=posX;
if(NumPos>1 && UseStopLoss )Changes_Stoploss(Mc1Number,NumPos);
【もしナンピン回数(オーダー数の合計)が更新されたら、Changes_Stoploss()関数にMc1Number,NumPosの条件を与えて処理させる。】
}①
時間軸による変更(サーバータイム[GTM+0]
int NH = NowHour+ServerTime_GMT;
MaShift = MaShift_Custom(NH);
【MaShift_Custom( )にNHを与えて、その結果をMaShiftに格納】
Xox = Xox_Custom(NH);
【Xox_Custom( )にNHを与えて、その結果をXoxに格納】

今回はここまでにしておきます。

2009/02/03

Mizutori_EAの説明(カスタムユーザー向け④)


前回の続きです。
※ご指示頂きましたので修正しました。(2009/2/11)
ここからは、注文・決済・注文の変更になりますが、汎用性を高くするために多くの無駄な作業が含まれています
※不具合が見つかりました。不具合の場所を赤字で書いておきます。
◆ ポジションの決済 ◆
void ClosePositions(int Close_Type ,int Oder_Type ,int MagicNumber)
【void型の関数は、処理後の値がない関数(処理値を返さない関数です。)】
【ClosePositionsという名前の自作関数で、決済タイプ(0:1つだけ決済する、1;すべて決済する)決済する注文の種別、マジックナンバー、を受けて処理を行います。】
{【①まで有効】
int Error ;
RefreshRates();
【値を最新のものにする。】
for(int i=OrdersTotal()-1;i>=0;i--)【注文がある分繰り返す】
{【②まで有効】
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break ; //注文ポジションの選択
【注文が、なければ処理を脱出する。】
if(OrderMagicNumber() != MagicNumber) continue; //マジックナンバー
【マジックナンバーが異なれば処理をスキップする。】
{ 【③まで有効】※不要かもしれません。
int type = OrderType();
【その注文のタイプを確認する。BUY or SELL】
if((type == OP_BUY && Oder_Type==SIGNAL_CLOSEBUY)||(type==OP_SELL && Oder_Type==SIGNAL_CLOSESELL))
【決済指示が来ている注文のタイプとその注文が同じタイプか確認し、同じタイプであるなら④内の処理を行う。】
{【④まで有効】
switch(type)【注文のタイプ別分儀】
{【⑤まで有効】
買ポジションに対する処理
case OP_BUY:【BUY注文の場合】
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, MediumSeaGreen);
 【決済注文を行う(この注文のチケットナンバー、この注文のロット数、売値、スリペ、チャート上の決済位置の印の色)】
Error = GetLastError();
【上記処理のエラーをErrorに格納】
if(Error!=0){Print("Close Positions Error OrderTicket = ", OrderTicket());}else{【⑥まで有効】
【もし、処理時にエラーがあれば、エラー報告しなければ以下の処理を行う。】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + " Close Buy");
【メールを送るようになっていれば、(   )内の文面でメールを送る。】
if(SignalAlert)Alert("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + " Close Buy");
【アラート設定がなされていれば、(  )内の文面でアラートを発生させる。】
}⑥
if(Close_Type==0){return(0);}
【1つだけ決済する場合は、この関数を終了する。】
break;【swithchからの脱出】
売りポジションに対する処理
case OP_SELL: 【SLL注文の場合】
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, DarkOrange);
【決済注文を行う(この注文のチケットナンバー、この注文のロット数、買値、スリペ、チャート上の決済位置の印の色)
Error = GetLastError();
【上記処理のエラーをErrorに格納】
if(Error!=0){Print("Close Positions Error OrderTicket = ", OrderTicket());}else{【⑦まで有効】
【もし、処理時にエラーがあれば、エラー報告しなければ以下の処理を行う。】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Close Sell");
【メールを送るようになっていれば、(   )内の文面でメールを送る。】
if(SignalAlert)Alert("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Close Sell");
【アラート設定がなされていれば、(  )内の文面でアラートを発生させる。】
}⑦
if(Close_Type==0){return(0);}
【1つだけ決済する場合は、この関数を終了する。】
break; 【swithchからの脱出】
}⑤
}④
}③
}②
}①
【処理値を返さなくていいので、return()がありません。】
◆ポジションの注文 ◆
void OrderPositions(int Order,int pok1,int pok2,int MagicNumber)
【戻り値のないOrderPositionsという名前の自作関数で、注文の種別、現在のBUY注文の数、現在のSELL注文数、マジックナンバーを受けて処理する。】
{ 【①まで有効】
//-------ロット数の計算
double StopLossLevel =0;
double Stp=0;
int pos = MathAbs(pok1 - pok2);
【現在の注文数をposに格納】
double Lots = 0;
if(Lot_Management){Lots=lotSizeCalc(pos);}else{Lots=Fixed_Lots;}
【ロット調整を行う場合は、lotSizeCalc自作関数を実行し、Lotsに格納。ロット調整をしない場合は、Fixed_Lots(指示値)をLotsに格納】
if(Order==SIGNAL_BUY)
【BUY注文の場合{②}内の処理を行う】
{【②まで有効】
Ticket=0;
if(AccountFreeMarginCheck(Symbol(),OP_BUY,Lots)<=0 || GetLastError()==134){【③まで有効】
【余剰証拠金を確認し、不足している場合{③}内を処理】
Print("We have no money. Free Margin = ", AccountFreeMargin());
【残高不足であることを記載する。】
return(0);【自作関数の終了】}
if (UseStopLoss){Stp= Ask-StopLoss*Point ;}else Stp = 0.0;
【損切り値を設定する場合、損切り値をstpに格納、設定しない場合は、stpに0を格納】
if (UseTakeProfit) TakeProfitLevel = Ask + (TPf*Point) ; else TakeProfitLevel = 0.0;
【利食い値を設定する場合、利食い値をTakeProfitLevelに格納、設定しない場合は、TakeProfitLevelに0を格納】
for(int bt=1;bt<= Order_Challenge ;bt++)【Order_Challenge(指示値)分{④}内を繰り返す】
{【④まで有効】
Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage*Point, Stp, TakeProfitLevel, "Buy(#" + MagicNumber + ")", MagicNumber, 0, DodgerBlue);
現在の通貨ペア、BUY注文、注文数、買値、スリペ、損切り値、利食い値、履歴に(Buy(#マジックナンバー))と記入、マジックナンバー、現在の時間、チャート上に記載される色を指示し、注文する。また、注文状況をTicketに格納】
if(Ticket > 0) 【注文が処理されたら】{【⑤まで有効】
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {【⑥まで有効】
【注文がされているか再度確認するために、注文を確認し、注文がされていれば】
Print("BUY order opened : ", OrderOpenPrice());
【(BUY order open 約定金額)と履歴に残す】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "@"+DoubleToStr(Lots,2)+"@ Open Buy");
【メール設定されていれば、( )内の文面でメールを送る。】
if(SignalAlert) Alert ("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "@"+DoubleToStr(Lots,2)+"@ Open Buy");
【アラート設定されていれば、( )内の文面でアラートを表示する。】
break ;【処理を抜け出す。】
⑥} else { ⇒ ⑥}⑤}else{⑦ 【不具合発見です。既設(赤部)だと1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになっています。変更が必要です。】
【変更内容は、1度目の確認が偽ならエラー処理をする。というものです。】
【2回目の確認は、本来注文の呼び出しがメインのため、エラー処理なしとしてみました。】
if(SignalAlert) Alert("Error opening BUY order : ", GetLastError());
【アラート設定がなされている場合、( )内を表示(エラー報告)】
Sleep(5000);//5秒間停止
【5秒間停止】
}【上記不具合のため、削除】
}⑦
}④
}③
if(Order==SIGNAL_SELL)
【SELL注文の場合{⑦}内の処理を行う】
{【⑦まで有効】
Ticket=0;
if(AccountFreeMarginCheck(Symbol(),OP_SELL,Lots)<=0 || GetLastError()==134){【⑧まで有効】
【余剰証拠金を確認し、不足している場合{⑧}内を処理】
Print("We have no money. Free Margin = ", AccountFreeMargin());
【残高不足であることを記載する。】
return(0); 【自作関数の終了】}⑧
if (UseStopLoss){Stp= Bid+StopLoss*Point ;}else Stp = 0.0;
【損切り値を設定する場合、損切り値をstpに格納、設定しない場合は、stpに0を格納】
if (UseTakeProfit) TakeProfitLevel = Bid - (TPf*Point) ; else TakeProfitLevel = 0.0;
【利食い値を設定する場合、利食い値をTakeProfitLevelに格納、設定しない場合は、TakeProfitLevelに0を格納】
for(int sc = 1;sc<= Order_Challenge ;sc++)【Order_Challenge(指示値)分{⑨}内を繰り返す】
{【⑨まで有効】
Ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage*Point, Stp, TakeProfitLevel, "Sell(#" + MagicNumber + ")", MagicNumber, 0, DeepPink);
【現在の通貨ペア、SELL注文、注文数、売値、スリペ、損切り値、利食い値、履歴に(Buy(#マジックナンバー))と記入、マジックナンバー、現在の時間、チャート上に記載される色を指示し、注文する。また、注文状況をTicketに格納】
if(Ticket > 0) 【注文が処理されたら】{【⑩まで有効】
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {【⑪まで有効】
【注文がされているか再度確認するために、注文を確認し、注文がされていれば】
Print("SELL order opened : ", OrderOpenPrice());
【(SELL order open 約定金額)と履歴に残す】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "@"+Lots+"@ Open Sell");
【メール設定されていれば、( )内の文面でメールを送る。】
if(SignalAlert) Alert ("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "@"+Lots+"@ Open Sell");
【アラート設定されていれば、( )内の文面でアラートを表示する。】
break ; 【return(0);の方がいいかもしれません。】
⑪} else { ⇒ ⑪}⑩}else{⑫ 【不具合発見です。既設(赤部)だと1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになっています。変更が必要です。】

【変更内容は、1度目の確認が偽ならエラー処理をする。というものです。】
【2回目の確認は、本来注文の呼び出しがメインのため、エラー処理なしとしてみました。】

if(SignalAlert) Alert("Error opening SELL order : ", GetLastError());
【アラート設定がなされている場合、( )内を表示(エラー報告)】
Sleep(5000);//5秒間停止
【5秒間停止】
} 【上記不具合のため、削除】
}⑫
}⑨
}②
}①
◆ Stoplossの変更(注文の変更)◆
void Changes_Stoploss(int MagicNumber,int pos)
【戻り値のないChanges_Stoplossという自作関数で、マジックナンバー、ナンピン回数を受けて処理します。】
{【①まで有効】
int Error ;
int Total = OrdersTotal()-1;
【注文数の合計をTotalに格納】
int K = Total-pos+1;※不具合処理のため削除
for(int i=Total;i>=K;i--) ⇒ for(int i=0;i> Total;i++) ※不具合発生のため変更
{【②まで有効】
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break ; //注文ポジションの選択
【注文の呼び出し、及び 注文がなければ、処理を脱出】
if(OrderMagicNumber() != MagicNumber) continue; //マジックナンバー
【マジックナンバーが異なればスキップ】
{ 【③まで有効】※たぶん要らない
int type = OrderType();
【その注文タイプをtypeに格納】
switch(type)【注文タイプの分儀】
{【④まで有効】
//買ポジションに対する処理
case OP_BUY:【BUY注文の場合】
OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss( )-Point*StopStep,OrderTakeProfit(),0,Yellow);
【注文の変更(注文番号、注文値、損切り値、利食い値、時刻、黄色)で変更を行う】
Error = GetLastError();
【エラーをErrorに格納】
if(Error!=0){Print("Changes Stoploss Error OrderTicket = ", OrderTicket());}
【エラーがあるなら、履歴に残す】
break;【処理を脱出】
//売りポジションに対する処理
case OP_SELL:【SELL注文の場合】
OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss( )+Point*StopStep,OrderTakeProfit(),0,Yellow);
【注文の変更(注文番号、注文値、損切り値、利食い値、時刻、黄色)で変更を行う】
Error = GetLastError();
【エラーをErrorに格納】
if(Error!=0){Print("Changes Stoploss Error OrderTicket = ", OrderTicket());}
【エラーがあるなら、履歴に残す】
break; 【SELL注文の場合】
}④
}③
}②
} ①
//+---------------------------------------------------------------- END ------------------------------------------------------------------+