Q
水平線を描画する機能を作っていますが、条件分岐がうまく理解できていません。
例えば、5分足にて、期間10のSMAが10本続けて価格が落ちている状態。
そこから数十分かけて、終値が上がってきたので、SMAも同様に上がってきた。
そして終値がSMAを上回ったので、そのときのSMAに水平線を描画したいとした場合の条件分岐とその時の結果を保持することがどうしてもできなくて困っています。
自作でifとforを組み合わせて試行錯誤しているのですが、どうしてもうまくいかないです。
例えば、結果を保持して描画が固定しない(終値がSMAを超えていると、常に水平線が上がってしまう)
水平線が保持されるが、テスターで描画が止まってしまったなどの現象でうまくいかない状態です。
ifとforの理解が足りないので、大変お恥ずかしながら一部抽出してご覧いただけますか?一部抽出しても全く意味はないのですが。上記の状態になってしまうため&全コードはとても長すぎるので一部抜粋致しました
// int count_bars=IndicatorCounted(); // int num= Bars-count_bars-1; //if(SMALow<=double iClose(NULL,0,iLo) &&SMALownow>SMALowpast) // ライン1から指定期間の本数を求める //for(int i=0; i<0;i ) //SMApast22=NormalizeDouble(iMA(NULL,0,SMAPeriod,0,MODE_SMA,PRICE_CLOSE,iLo-(i))Digits()); |
A
サンプルソース(SMA判定)を添付しましたので、サンプルソースで確認してソースコードを確認してみて下さい。
画像に解説を記載しましたので、添付画像を参照して下さい。
思い通りに動作しなかった場合は、紙にチャートを描いてイメージしてみるといいですよ。
ソースコードを書く前に、添付画像のようにどうすれば実現できるか絵を描いてみて、
絵で描いた動作をを言葉で表現してみてから、
それをソースコードに落とし込むといいですよ。
それでも上手くいかない場合、
例えば
>結果を保持して描画が固定しない(終値がSMAを超えていると、常に水平線が上がってしまう) の場合、 その動作からSMAを上抜けしている場合に常時水平線を描画しているのが原因である事が想像出来ます。 では、最初のSMA上抜け時だけ水平線を描画させるにはどうすれば良いか? SMA上抜け判定したら、それ以前の終値がSMAを下回っているかをチェックすればいいのではないか? 何が原因かを考えて、それを解決するにはどうすれば良いか? というふうに考えてみると不具合修正が出来るようになります。 |
//+------------------------------------------------------------------+ //| TestSMAHLine.mq4 | //| yuki | //| https://yukifx.web.fc2.com/ | //+------------------------------------------------------------------+ #property copyright "yuki" #property link "https://yukifx.web.fc2.com/" #property version "1.00" #property strict #property indicator_chart_window // カスタムインジケータをチャートウインドウに表示する // インジケータプロパティ設定 #property indicator_buffers 1 // カスタムインジケータのバッファ数 #property indicator_color1 clrWhite // インジケータ1の色 #property indicator_width1 1 // インジケータ1の太さ // マクロ定義 #define IND_MIN_INDEX 2 // 最小バー数 #define OBJ_HEAD ( __FILE__ + "_" ) // オブジェクトヘッダ名 // インジケータ表示用動的配列 double _IndBuffer1[]; // インジケータ1表示用動的配列 // インプットパラメータ input int _InputMAPeriod = 10; // 移動平均期間 //+------------------------------------------------------------------+ //| OnInit(初期化)イベント //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer( 0, _IndBuffer1 ); // インジケータ1表示用動的配列をインジケータ1にバインドする return( INIT_SUCCEEDED ); // 戻り値:初期化成功 } //+------------------------------------------------------------------+ //| OnDeinit(アンロード)イベント //+------------------------------------------------------------------+ void OnDeinit( const int reason ) { ObjectsDeleteAll( // 追加したオブジェクトを全削除 0, // チャートID OBJ_HEAD // オブジェクト名の接頭辞 ); } //+------------------------------------------------------------------+ //| OnCalculate(tick受信)イベント //| カスタムインジケータ専用のイベント関数 //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, // 入力された時系列のバー数 const int prev_calculated, // 計算済み(前回呼び出し時)のバー数 const datetime &time[], // 時間 const double &open[], // 始値 const double &high[], // 高値 const double &low[], // 安値 const double &close[], // 終値 const long &tick_volume[], // Tick出来高 const long &volume[], // Real出来高 const int &spread[]) // スプレッド { int end_index = Bars - prev_calculated; // バー数取得(未計算分) if ( end_index <= IND_MIN_INDEX ) { // 直近数本は常時更新 end_index = IND_MIN_INDEX; } if ( Bars <= IND_MIN_INDEX ) { // ヒストリカルデータ不足時 return 0; // 全て再計算が必要なので、計算済みバー数を0にして終了する } for( int icount = 0 ; icount < end_index ; icount++ ) { double get_ma = iMA ( // 移動平均算出 Symbol(), // 通貨ペア Period(), // 時間軸 _InputMAPeriod, // MAの平均期間 0, // MAシフト MODE_SMA, // MAの平均化メソッド PRICE_CLOSE, // 適用価格 icount // シフト ); _IndBuffer1[icount] = get_ma; // インジケータ1に移動平均を設定 } JudgeDispHLine(); return( rates_total ); // 戻り値設定:次回OnCalculate関数が呼ばれた時のprev_calculatedの値に渡される } //+------------------------------------------------------------------+ //| 水平線表示判定 //+------------------------------------------------------------------+ void JudgeDispHLine(){ int end_index = Bars - 10; for( int icount = 0 ; icount < end_index ; icount++ ) { double get_ma = iMA ( // 移動平均算出 Symbol(), // 通貨ペア Period(), // 時間軸 _InputMAPeriod, // MAの平均期間 0, // MAシフト MODE_SMA, // MAの平均化メソッド PRICE_CLOSE, // 適用価格 icount // シフト ); // 終値がSMAを上回っている場合 if ( get_ma < Close[icount] ) { // SMA上抜けする前の終値10本がSMAを下回っているか判定 int under_count = 0; for ( int jcount = icount + 1; jcount < end_index; jcount++ ) { double check_ma; check_ma = iMA ( // 移動平均算出 Symbol(), // 通貨ペア Period(), // 時間軸 _InputMAPeriod, // MAの平均期間 0, // MAシフト MODE_SMA, // MAの平均化メソッド PRICE_CLOSE, // 適用価格 jcount // シフト ); if ( check_ma > Close[jcount] ) { under_count++; if ( under_count >= 10 ) { DispObjHLine(get_ma); // 水平線を描画 return; // 処理終了 } } else { // 一度でもSMAを上回っている場合 break; // ループ終了 } } } } } //+------------------------------------------------------------------+ //| 水平線オブジェクト描画 //+------------------------------------------------------------------+ void DispObjHLine( double in_rate ) { string obj_name; // オブジェクト名 obj_name = StringFormat( "%HLine" , OBJ_HEAD ); if ( ObjectFind( obj_name ) >= 0 ) { // オブジェクト名重複チェック // 重複している場合 ObjectDelete( obj_name ); // 指定したオブジェクトを削除する } ObjectCreate( // オブジェクト生成 obj_name, // オブジェクト名 OBJ_HLINE, // オブジェクトタイプ 0, // ウインドウインデックス 0, // 1番目の時間のアンカーポイント in_rate // 1番目の価格のアンカーポイント ); }