エンジニアの備忘録

学んだ事をアウトプットしていきます

MT4がフリーズして開かない時の直し方+ヒストリーデータの土日足の消し方

MT4がフリーズして開かない時の直し方

チャートを開きすぎたせいで、MT4がフリーズして開くことすらできなくなりました。

ググっても対処法しか載っていなかったので、同じ境遇に陥った人用に残しておきます。

結論から書くと、インジケータorヒストリーデータをMT4ファイルから一旦消してしまいます。

・インジケータの処理が多すぎてフリーズ

・チャートを表示しすぎたorロウソク足の表示が多すぎてフリーズ

基本的にこの2つがフリーズの主な原因です。

f:id:pmpmcherry:20220215171744p:plain

こんな流れでターミナルまで辿るとMQL4のデータがあるので、そこからindicatorとhistoryの中身を一旦別のファイルに移して置いて、再度MT4を開くことで直ります。

直ったら開いていたチャートを全部消してしまって、再度別に置いていた2つのデータを元に戻す。

対処してても意図しない形でフリーズは起きるので、そういう時用にデスクトップにMQL4のショートカットを用意しておくのをお勧めします。

ヒストリーデータの土日足を消す

FXDDから1分足データを入れる→Period_Converter_ALLで全足作成

という流れだけで済ますと、土日に余計な足が入ります。

金曜から月曜のチャートの間に値動きのない足が2本入っていたら、そのチャートデータは正しくないモノになります(区間区切り線が3本続いてたりする)

EAの内容によっては検証結果に大幅なズレが生じるので気を付けましょう。

 

FXDDから1分足データをDL

ネット内からhst2csvというhst→csv変換するスクリプトをDL(ググれば出てくる)

Period_Converter_ALLというスクリプトをDL(ググれば出てくる)

DLした足データをMQL4のfile内に入れる

チャート表示本数をMAX、プロキシサーバを有効に☑、DLした通貨ペアのヒストリーデータを削除して再起動

hst2csvスクリプトを起動する(なんでもいいのでチャートを開いとかないと使えない)

※hstファイル名はDLした通貨ペアのファイル名を正しく入力する

完了したらfile内にcsvファイルが出来ているので、そのファイルをヒストリーセンターからインポートする

Period_Converter_ALLで上位時間足のチャートを作成

 

この流れで行えば土日の余計な足は生成されません。

5分足しか使わないような人は、MT4内に最初から入っているPeriod_Converterを使えば1分足データを整理しなくても、土日足が入ってないチャートを作成できたはずです。

 

※どの記事でも紹介されているPeriod_Converter_ALLというスクリプトを使って1分足のゴミデータから全時間足を一気に作成することで、全ての時間足に土日の余計な足が生成されたチャートが出来上がります。

行うなら土日データの入ってない1分足から作成しましょう!という話です。

 

色々な逆張りロジックを検証

日足の高安値で逆張り

 

日足の高安値+RSIで逆張り

 

週足の高安値で逆張り

 

週足の高安値+RSIで逆張り

 

移動平均からの乖離率で逆張り

HLブレイクEA検証

 

現状テスト

前回作ったEAの検証をしていきます。

パラメータは以下の通り↓

パラメータ
利食い +50pips
損切り -50pips
ロット0.1固定
HL期間1日前

ロットは固定にしておきます。

まずは最適化なしでバックテストさせます。

2016年〜2020年の1年刻みでサンプル4個でテストしました

f:id:pmpmcherry:20220116002337p:plain

2016/1/1〜2020/12/31 資産推移

f:id:pmpmcherry:20220116002520p:plain

2016/1/1〜2020/12/31 USD/JPY 5分足

全然ダメ。

2016年だけプラス成績なのは、逆V字でボラが強いトレンド相場でした。

f:id:pmpmcherry:20220116005511p:plain

時間毎の損益

欧州時間は一方向に偏りやすい特徴があるので、欧州時間付近にプラス収益が集まっているのかもしれない🤔
5分足以上でテストした結果、サンプルサイズが足りなすぎたので省きます。

1分足もトレード数が少し増えた以外の変化はありませんでした。

ストップ・リミットの最適化(2016/1/1~12/31)

ロング注文

まずはロングに絞ってリミットを10pipsスタート→10pips加算→150pipsまで最適化します。

ストップは5pips→5pips加算→30pipsで。

f:id:pmpmcherry:20220116214947p:plain

2016年 ロング ストップ・リミット最適化

f:id:pmpmcherry:20220117004903p:plain

ロング ストップpipsの割合

f:id:pmpmcherry:20220117005003p:plain

ロング リミットpipsの割合

ショート注文

さっきと全く同じ条件の最適化をします。

f:id:pmpmcherry:20220116232308p:plain

2016年 ショート ストップ・リミット最適化

f:id:pmpmcherry:20220116235315p:plain

ショート ストップpipsの割合

f:id:pmpmcherry:20220116235024p:plain

ショート ロングpipsの割合

PF1.20以上のサンプルで構成されています。

ショート→ストップ15pips・リミット100pips

ロング→ストップ5pips・リミット20pips

 

明日はこの最適化したパラメータで2017年をフォワードテストします。

▲2022年1月17日0:54更新▲

ウォークフォワードテスト結果

f:id:pmpmcherry:20220117173353p:plain

..2017年フォワード分析の結果

んー、厳しい(-_-;)

ドル円の2017年は1年通してずっとレンジ相場でしたから、ブレイクアウト手法との地合いが悪いんですよね。。。

今行った一連の作業を4セットし、それを繋げたフォワード分析の損益グラフを繋げて見ると

f:id:pmpmcherry:20220118021521p:plain

2016~2019 ウォークフォワード分析結果の損益グラフ

考察

f:id:pmpmcherry:20220118024811p:plain

時間帯毎の損益グラフ

時間別での損益も確認しておきます。

ブレイクエントリーポイントとして適している場所はこの時間帯な事が分かります。

欧州時間付近のブレイクにエッジがあるのは経験則からなんとなく分かってましたが、単純なシステムでも利益が集中している所を見る限り間違いない?🤔

と思いたいが、サンプルサイズが13時〜16時合わせて77回と少ないので怪しい。

 

それとpips指定での利食い損切りはボラに影響を受けまくるので、違う決済方法を考えるのも課題かなと思いました。

まだHLを使った手法を諦めたわけではないので、スイング・長期トレードに切り替えて再度試行錯誤してみます!

勝率50%でも資金は増えるのか?という資金管理の仮説

前置き

FXの資金管理に代表的な例として固定ロット、マーチンゲール、逆マーチンゲール、N%ルールなどを含め様々ある。

カジノでいうベッティング。

ちなみにコイン投げのような確率半々の独立事象は、色々とベット法を調整しても、ベット法でプラスの期待値には持っていけないという式が数学で成り立っているらしい。

例えば、ルーレットは1マスに賭けたときの勝率は50%という印象が強いが、厳密にはカジノ側が技術介入出来るので理論武装してもプラスの期待値にはならないので、やればやるほど、プレイヤーの資金はマイナスに収束していく。

あるギャンブラーは赤が連続で起きた場面だけ「もう赤はこないだろう」という考えから黒にベットし続けて大金持ちになったという伝説がある。

ただ、この方法はギャンブルで大儲けした人のたまたま話でしかない。

赤が出た後、赤が出る確率も黒が出る確率も当然等しく、赤が5回出たからといって次黒が出やすい確率には影響を与えないからだ。

連続で赤が続いたらもうそろそろ黒が出るだろうというバイアスがかかりやすい。

これを理解した上であえて進める。

重要なのはその資金管理で元手10万破産する確率が高くても、100%リターンする確率が上回れば良い。

仮説1:負の従属性が高いとき

FXでのリスクリワードが1:1かつ勝率が50%を下回っていない条件が必須

負の従属性があるとは、連敗と連勝が続かない傾向があること。

勝ちは負けを生み、負けは勝ちを生みやすい。

負けが続くほど次に勝つ可能性が高まっているなら掛け金を増やすべきで、勝ちが続くほど次負ける確率が高まっているなら掛け金を減らすのは合理的じゃないだろうか?

資金10万スタートで収益の基準を1万で考えた時の例↓

回数 1回 2回 3回 4回 5回 6回 7回 8回 9回 10回
収益 +1万 −5千 −1万 +3万 −5千 +1万 +5千 −2500 −5千 +7500
勝敗 勝ち 負け 負け 勝ち 負け 勝ち 勝ち 負け 負け 勝ち
資産推移 ¥110,000 ¥105,000 ¥95,000 ¥125,000 ¥120,000 ¥130,000 ¥135,000 ¥132,500 ¥127,500 ¥135,000
賭け方 次減らす 次増やす 次増やす 次減らす 次増やす 次減らす 次減らす 次増やす 次増やす 次減らす
破産 ¥5,000 ¥10,000 ¥15,000 ¥30,000 ¥60,000 5連敗、32分の1で破産    

この負の従属性を上手く利用すれば、目標金額を定めた場合資金管理だけで達成可能。

独立事象だと33回トレードしたときに1回は破産する計算だが、負の従属性があり1敗後に連敗を重ねていく確率は50%ではないので、実際の所は32分の1という確率で破産はしない。

上の表は1万を基準にしてるが、毎トレードの収益を基準にしたらブレ幅は大きくなる。

回数 1回 2回 3回 4回 5回 6回 7回 8回 9回 10回
収益 +1万 −5千 −1万 +3万 -15000 30000 15000 -7500 -15000 45000
勝敗 勝ち 負け 負け 勝ち 負け 勝ち 勝ち 負け 負け 勝ち
資産推移 ¥110,000 ¥105,000 ¥95,000 ¥125,000 ¥110,000 ¥140,000 ¥155,000 ¥147,500 ¥132,500 ¥177,500
賭け方 次減らす 次増やす 次増やす 次減らす 次増やす 次減らす 次減らす 次増やす 次増やす 次減らす

金額が大きくなる分、4連敗すると破産になり回転が速くなる。

逆に資金を小さくすれば破産への連敗数を伸ばすことができるが、回転が遅くなる。

結論

まず、負つの従属性があるロジックを持ちつつ勝率50%以上リワード比率1あるEAが必要な事。

最大のメリットはトントン成績の手法を稼げる手法に昇華出来ること。

やってることはかなりギャンブルチックだけど・・・

 

ウォークフォワード分析(固定化なし)

期間早見表

何十年規模の過去データにできるだけ依存したくないので、直近5年付近を目途にする。

長年機能するようなロジックは固定の方が適している。

評価基準は純利益とPFを使用(人それぞれ)

ウォークフォワード分析の詳細はパンローリング社出版の「システムトレード検証と実践」に書いています。

月トレード平均回数が20回 約600回
2016年1月〜6月(最適化) 2016年7月〜12月(フォワードテスト)
2017年1月〜6月(最適化) 2017年7月〜12月(フォワードテスト)
2018年1月〜6月(最適化) 2018年7月〜12月(フォワードテスト)
2019年1月〜6月(最適化) 2019年7月〜12月(フォワードテスト)
2020年1月〜6月(最適化) 2020年7月〜12月(フォワードテスト)

 

月トレード平均回数が10回 約600回
2015年1月〜12月(最適化) 2016年7月〜12月(フォワードテスト)
2016年1月〜12月(最適化) 2017年1月〜12月(フォワードテスト)
2017年1月〜12月(最適化)

2018年1月〜12月(フォワードテスト)

2018年1月〜12月(最適化) 2019年1月〜12月(フォワードテスト)
2019年1月〜12月(最適化) 2020年1月〜12月(フォワードテスト)

 

月トレード平均回数が5回 約300回
2015年1月〜12月(最適化) 2016年7月〜12月(フォワードテスト)
2016年1月〜12月(最適化) 2017年1月〜12月(フォワードテスト)
2017年1月〜12月(最適化) 2018年1月〜12月(フォワードテスト)
2018年1月〜12月(最適化) 2019年1月〜12月(フォワードテスト)
2019年1月〜12月(最適化) 2020年1月〜12月(フォワードテスト)

 

f:id:pmpmcherry:20220113161502p:plain

 

 

前日の高値・安値を使ったブレイクアウトEAを作ってみる

作成前に懸念点を明らかにする

懸念点は往復エントリー。

「安値をブレイクで売り」がメインなのに、ブレイク後安値ラインを上抜けでエントリーされるのは望ましくない。

複数エントリー無しにしても、ブレイク後に決済して戻ってきた場合だとエントリーされてしまう。

今のレベルで思いつく解決法は

①インジケータの高値と安値の区別化

移動平均線でフィルターをかける

③条件文を追加する

お手軽さに優先順位を付けるならこうなる ② > ③ > ① 

②なら移動平均より下であればロングエントリーしない、という内容で防げそう(チャート画面は5分足想定)

しかしこれはこれでMAの数値次第でロングして欲しいときにエントリーしない状況も出てくる(-_-;)

③はどうだろうか?例えば、今日既にエントリーしていた場合はエントリーしない。

これなら1回目のブレイクだけはちゃんとエントリー可能、もしその後にライン付近で上抜け下抜けを繰り返す値動きが起きても本来望んでいないエントリーは発生しないはず。

一旦は③採用で進めます。

 

EAの概要

最初はできるだけシンプルに基盤を作成し、それを元に改良を加えていきます。

【エントリー基準】

  • 前日の高値価格より、現在の終値価格が高いなら買い
  • 前日の安値価格より、現在の終値価格が安いなら売り

【クローズ基準】

【資金管理】

  • 口座残高の2%を1トレードの損失額になるようにロットを算出

【備考】

  • 複数ポジションを持たない
  • エントリーは1日1回まで
  • クロス円

 

定義ができたので、明日はエントリー基準の判定に使う高値安値のオブジェクトをEAに組み込めるように準備します。(以下、高値=H 安値=L)

 

 

HLラインをオブジェクト表示したインジケータを使う予定でしたが、半日かけてもスキル不足で上手くEAに組み込めそうになかったので諦めました。

オブジェクト名を取得し、そこから価格を取得したら出来るらしいが・・・上手く動かなかった(-_-;)

結局オブジェクトのEA化は諦めて、インジケータバッファを用いたHLインジケータを作ったので、それをiCustm関数を使ってEAにしようと思います。

エントリー判定

//+------------------------------------------------------------------+
//| エントリー判定
//+------------------------------------------------------------------+
ENUM_HL_Break HLBreak_Judge(){
   
   ENUM_HL_Break ret = MAC_NULL;
   
   //安値ラインの価格を取得
   double low_line = iCustom(Symbol(),PERIOD_CURRENT,"EA用HLインジ",0,1);
   //高値ラインの価格を取得
   double high_line = iCustom(Symbol(),PERIOD_CURRENT,"EA用HLインジ",1,1);
   //終値を取得
   double temp_close1 = iClose(Symbol(),PERIOD_CURRENT,1); //足1個前
   double temp_close2 = iClose(Symbol(),PERIOD_CURRENT,2); //足2個前
   
   //高値を上抜け
   if(high_line > temp_close2 && high_line < temp_close1){
      ret = MAC_UP_CHANGE;
   //安値を下抜け  
   } else if(low_line < temp_close2 && low_line > temp_close1){
      ret = MAC_DOWN_CHANGE;
   }
   return ret;
}

iCustom関数について補足:

引数3の"ファイル名"はMQL4>indicator内にいれておかないと、カスタムインジケータ値を引っ張ってくる事が出来ません。

例えばindicatorファイル内にフォルダを作って、その別フォルダにiCustom関数で使いたいインジケータを保存している場合使えません。

 

  • 前日の高値価格より、現在の終値価格が高いなら買い
  • 前日の安値価格より、現在の終値価格が安いなら売り

足1本前と2本前の終値価格を使ってブレイクしたかのエントリーを判定しています。

クローズ判定

//+------------------------------------------------------------------+
//| 決済オーダー条件の判定
//+------------------------------------------------------------------+
void JudgeClose(ENUM_HL_Break in_hl_break){
   
   bool close_bool    = false;  //決済判定のスイッチ
   double entry_rate  = OrderOpenPrice();
   double sell_close  = 0;
   double buy_close   = 0;
   
   sell_close = entry_rate - 0.500;
   buy_close  = entry_rate + 0.500;
   
   double set_sell_close = NormalizeDouble(sell_close,Digits);
   double set_buy_close  = NormalizeDouble(buy_close,Digits);
   
  if(_StPositionInfoDate.ticket_no > 0){  //ポジション保有
     if(_StPositionInfoDate.entry_dir == OP_SELL) {  //売りポジなら
         if(set_sell_close > Close[1])
         close_bool = true;
         
     } else if(_StPositionInfoDate.entry_dir == OP_BUY){  //買いポジなら
         if(set_buy_close < Close[1])
         close_bool = true;
     }

 

取得したエントリー価格から指定したpips幅をオフセットした値と、足1本前を比較してクローズ判定をしています。

OrderModify関数を使ってストップ・リミットを注文変更しているので、二重チェックで同条件のクローズ判定が執行されます。

ないとは思いますが、なんらかのバグで片方の決済が行われなかった場合、もう片方が執行してくれるので安心です。

金管

//+------------------------------------------------------------------+
//| 新規エントリー                                                                 |
//+------------------------------------------------------------------+
bool EA_EntryOrder(bool in_long)    
  {
  //ロット取得
   double temp_lot = Teiritu_CalcLots(50,2);

新規エントリー情報で取得しておきます。

  • 口座残高の2%を1トレードの損失額になるようにロットを算出

自作関数です。引数1にpips幅、引数2に%値入力でこの条件のロットが毎トレード算出されます。

 

複数ポジションを持たない条件は以前作ったBBと一目EAとほとんど同じ作りです。

ここで一旦動作テストをします。

f:id:pmpmcherry:20220113002721p:plain

安値を下抜けした終値で売られ、ストップ設定値で損切りされています。

高値を上抜けした終値で買われ、リミット設定値で利着されています。

エントリー、クローズ判定は大丈夫そうです。

f:id:pmpmcherry:20220113003026p:plain

ログ出力の内容です。

ロット数に変化が起きているので、変動制ロットになっています。

表示チャートの足更新時に注文変更が発生、パット見で計算しても±50pipsで設定されているのが分かります。

これで大体は完成しました。

 

このまま深刻なバグが見つからなければ、明日には完成しそう。

明日は「エントリーは1日1回まで」の条件を付けくわえていこうと思います。

▲2022/01/13-0:38 更新▲

 

OrdersHistoryTotalという関数がクローズ済み注文数を返してくれます。

しかし、口座履歴で指定した設定に依存してるようなのでリアルトレードではこれを使えば制御できますが、バックテストでは制御できませんでした(バックテストでは口座履歴が設定できないため)

なので今回はGogojungleの書き込みで見つけた、getTradeCountDailyという関数を使います。

引数にEAのマジックナンバーを入れると、当日にエントリーした回数を返してくれます。

これをエントリー判定の中間処理に書いて

int order_history = getTradeCountDaily(MAGIC_NO);
//本日既に決済済み注文があった場合は注文しない
   if(order_history > 0){
      entry_bool = false;
   }

すると↓

f:id:pmpmcherry:20220113235203p:plain

売りエントリー損切り後、もう一度安値を終値で割りましたが追加でエントリーされませんでした!

ひとまず、仕様書の内容は取り込めたので完成です。

これからやること

【最適化】

【その他】

  • 一日一回エントリー条件を高値ブレイクと安値ブレイクで分ける
  • ブレイクしたら逆張り
  • ドルストレートVer.も別で作る
  • 逆張りと順張りのポートフォリオ運用

 

 

 

pythonで重回帰分析

重回帰分析について:

単回帰分析と違い独立変数が複数ある。また、当てはまりの良い直線ではなく最も当てはまりの良いモデルを探すことが目的。

決定係数、自由度修正済み決定係数、P値から独立変数が従属変数に与える影響が低いと判断できた場合、分析に必要のない独立変数データは削除する。

(例:データAの単回帰分析と重回帰分析を比較した。後者のR²値は下がり説明力も

   下がった。また、独立変数BのP値は異常に高く従属変数に影響を与えている可能 

   性が低いので削除した)  

 

前回の不動産データに独立変数yearを追加して重回帰分析を行った結果↓

OLS Regression Results
Dep. Variable: price R-squared: 0.776
Model: OLS Adj. R-squared: 0.772
Method: Least Squares F-statistic: 168.5
Date: Fri, 10 Dec 2021 Prob (F-statistic): 2.77e-32
Time: 06:31:19 Log-Likelihood: -1191.7
No. Observations: 100 AIC: 2389.
Df Residuals: 97 BIC: 2397.
Df Model: 2    
Covariance Type: nonrobust    
  coef std err t P>|t| [0.025 0.975]
const -5.772e+06 1.58e+06 -3.647 0.000 -8.91e+06 -2.63e+06
size 227.7009 12.474 18.254 0.000 202.943 252.458
year 2916.7853 785.896 3.711 0.000 1357.000 4476.571
Omnibus: 10.083 Durbin-Watson: 2.250
Prob(Omnibus): 0.006 Jarque-Bera (JB): 3.678
Skew: 0.095 Prob(JB): 0.159
Kurtosis: 2.080 Cond. No. 9.41e+05

決定係数はどちらも約+0.03上がっており、ばらつきへの説明力は上昇。

独立変数yearのP値は低く、従属変数に与える影響は高い。

結論、価格と築年数には関係性があるといえる。