X
私の目的は、指定された時間枠と日数の間の最高値と最低値から測定するチャート上に長方形のオブジェクトを作成することです?
チャートにオブジェクトを作成する方法は知っていますが、それを何日も前に繰り返す方法がわかりませんX
。どうすればこれを達成できますか?Forループが良いアプローチになるのではないかと考えていましたか?いくつかのガイダンスを使用できます。
X
私の目的は、指定された時間枠と日数の間の最高値と最低値から測定するチャート上に長方形のオブジェクトを作成することです?
チャートにオブジェクトを作成する方法は知っていますが、それを何日も前に繰り返す方法がわかりませんX
。どうすればこれを達成できますか?Forループが良いアプローチになるのではないかと考えていましたか?いくつかのガイダンスを使用できます。
このコードを試してください (Expert Advisor)。わかりました、効率的ではありません (すべてのティックを再計算するため) が、私は概念をかなりよく示しています。
そのコードは次のとおりです。
//+------------------------------------------------------------------+
//| GeraldHighLowV0R1.mq4 |
//| Copyright 2015, joseph.lee @ fs [dot] com [dot] my |
//| http://www.fs.com.my/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, joseph.lee @ fs [dot] com [dot] my"
#property link "http://www.fs.com.my/"
#property version "1.00"
#property strict
extern int viTimeOfDayStartHour = 3;
extern int viTimeOfDayEndHour = 9;
extern int viDaysToDraw = 10;
void OnTick() {
string vsGlobalDebug = "";
datetime vdCurrentDayStart = iTime(Symbol(), PERIOD_D1, 0); //Get Broker Today DateTime as of Midnight
ObjectsDeleteAll();
//---------------------------------------------------------------
//Process [viDaysToDraw] number of days (**Sat/Sun is included)
//---------------------------------------------------------------
for(int viDay=0; viDay<viDaysToDraw; viDay++) {
datetime vdDateOfSection = vdCurrentDayStart-(viDay*PERIOD_D1*60); //Get Section Midnight DateTime
datetime vdSectionStart = vdDateOfSection + (viTimeOfDayStartHour*PERIOD_H1*60); //Add Hours to Mark start of section
datetime vdSectionEnd = vdDateOfSection + (viTimeOfDayEndHour *PERIOD_H1*60); //Add Hours to mark End of section
//----------------------------------------------------------------------
//Calculate the number of bars between (inclusive) Start and End time
//----------------------------------------------------------------------
int viSectionEndBarIndex = iBarShift(Symbol(), PERIOD_CURRENT, vdSectionEnd,false);
int viSectionStartBarIndex = iBarShift(Symbol(), PERIOD_CURRENT, vdSectionStart,false);
int viBarCountBtwStartAndEndHour = viSectionStartBarIndex-viSectionEndBarIndex+1;
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//Find the Highest/Lowest Bar index within the Day Section
//-----------------------------------------------------------------
int viSectionHighestBar = iHighest(Symbol(), PERIOD_CURRENT, MODE_HIGH, viBarCountBtwStartAndEndHour, viSectionEndBarIndex);
int viSectionLowestBar = iLowest(Symbol(), PERIOD_CURRENT, MODE_LOW, viBarCountBtwStartAndEndHour, viSectionEndBarIndex);
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//Find the Highest/Lowest Price within the Day Section
//-----------------------------------------------------------------
double viSectionHighestPrice = iHigh(Symbol(), PERIOD_CURRENT, viSectionHighestBar);
double viSectionLowestPrice = iLow( Symbol(), PERIOD_CURRENT, viSectionLowestBar);
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//Add Verbose/Debug Info for display
//-----------------------------------------------------------------
StringAdd(
vsGlobalDebug, "\n[Day" + IntegerToString(viDay) + "]: "
+ "Start: " + TimeToString(vdSectionStart)
+ ", Lowest: " + DoubleToString(viSectionLowestPrice,Digits)
+ ", End: " + TimeToString(vdSectionEnd)
+ ", Highest: " + DoubleToString(viSectionHighestPrice,Digits));
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//Crete Rectangle Object for the Day section
//-----------------------------------------------------------------
string vsObjName = "HLDay" + IntegerToString(viDay);
ObjectCreate(0, vsObjName, OBJ_RECTANGLE, 0, vdSectionStart, viSectionLowestPrice, vdSectionEnd, viSectionHighestPrice);
ObjectSetInteger(0, vsObjName, OBJPROP_COLOR, clrDarkGreen);
ObjectSetInteger(0, vsObjName, OBJPROP_WIDTH, 0);
ObjectSetInteger(0, vsObjName, OBJPROP_BACK, true);
ObjectSetInteger(0, vsObjName, OBJPROP_SELECTABLE, false);
//-----------------------------------------------------------------
}
ChartRedraw();
//-----------------------------------------------------------------
// Show Debug/Verbose Info
//-----------------------------------------------------------------
Comment("\n" + vsGlobalDebug );
}
TimeFRAMEは、市場イベント フローの「時間ベースのフレーミング」に対して業界全体で受け入れられている用語であり、何十年もの間、そのような意味を標準化してきました。
自然時間の流れにおける週末関連のギャップと、上記のタスク定義の性質により、以下のコード スニペット ( PERIOD_D1
、PERIOD_H1
およびPERIOD_CURRENT
依存関係を隠します(不明(暗黙的) ため、まったく使用されませんでした) )。これにより、ポインターのカウントとバックステッピング インデックスの更新 (^PTR->TimeSERIES) が可能になります。
したがって、さらなる開発全体を通して、特定のタスク定義の下でaGreenBOXに別の用語を使用し、aTimeDOMAIN にバインドされた属性を別の方法で呼び出しましょう -- aTimeWINDOW & al (ただし、TimeFRAME ではありませんか?)
最も単純な形式では、以下に示すextern
-s のセットを使用します。GUI レイヤー アプリケーションがよりスマートで複雑になる場合や、 XTO ( e X ecute - Trade - Operation(s) )extern
に直接インターフェイスする場合、コンストラクターは危険であることに注意してください。
#property strict
extern int aGreenBoxWindow_HOUR__ENDs = 7; // aTimeWINDOW.ends <<- 05:00 - 07:00 [GMT-ABCD]
extern int aGreenBoxWindow_HOURs_WIDE = 2; // aTimeWINDOW.width
extern int aGreenBoxWindow_nDAYs_BACK = 4; // aTimeWINDOW.repeatDays
int aCallLockPTR = 0;
string anObjNamePREFIX = "aGreenBOX.id=";
XTO 操作がいくつかの GUI レイヤー要素 ( -triadeのビジュアル部分) に自動的にバインド/フックされる、MT4 に基づくリアルタイムの拡張取引サービスの場合、コンストラクターにバインドされた変数はむしろ回避する必要があります。それらの値の変更 ( MT4アーキテクチャ設計による)は、リアルタイム拡張サービスのモデルとコントローラー部分の両方でリセットと再入不可の衝突を引き起こし、そのような取引サービスは致命的に危険です。と XTO を使用します。M
V
C
extern
extern
-sを使用しない Augmented Trading Services のパラメータ化extern
リアルタイムで運用される拡張取引サービスのために、実行中のサービスに対する の壊滅的な影響を回避するためのより優れた (そしてより安全な) 方法があります。他にも、プロセス間/分散コンピューティング メッセージングを使用するのが最も好きです。これにより、主にMT4-Terminal がプライベート クラウドベースの取引インフラストラクチャ内のノードになり、 -MQL4
ベースの EA がシンフォニック オーケストラ内で再生を開始します。オーケストレーションされた手段 (AI/ML-NeuralNetwork の意思決定計算プロセスであろうと、ポートフォリオ最適化の量子モデルのための GPU ベースの共分散行列評価器であろうと、簡単に言えば、このようなものはすべてプロセスを「指示」/「命令」することができますMQL4
。中身"MT4-スムーズで中断のない、リアルタイムで、ノンブロッキングで、完全に非同期のターミナル、魅力的に聞こえませんか? はい、そうです!これを一度表示すると、約 1 [ms] 以下になります
UI 設計の領域に足を踏み入れると、(最初は隠れていた) 問題は UI 制御ループと呼ばれ、全体的な UI 応答性 (UI がMMI
( M
anachine M
-interface I
) と外部ストリームの両方に応答してどれだけ速く動くか) と呼ばれます。入力」(マウスクリック / マウス移動 / マウスドラッグ&ドロップ / aMarketEVENT / など)。
XTO/MVC優先/MVC遅延ビジュアル部分の再描画操作に新しいものをもたらさない、反復的なタスクの非効率的な呼び出しを回避するために、適切なポリシングを導入する必要があります。
ジョセフの提案に敬意を表して、UIプロセスをそれぞれのブロックタスクとして直接ハングアップするOnTick()
TickArrivalEVENT
ことは原則として可能ですが、XTOの製品グレードのソフトウェアとCPU/メモリアクセス/db.POOLリソースの両方で致命的に危険です。処理能力の浪費 (通常は他のタスクに必要)
int init(){
// ------------------------------------------- // ------------------------
aGreenBoxWINDOWs_Update(); // .init
aCallLockPTR = iBars( NULL, PERIOD_H1 ); // .set a CPU-clock saving LOCK
// ------------------------------------------- // ------------------------
}
int start(){
// ------------------------------------------- // -----------------
// HIGH-PRIORITY OPERATIONS
// ...
// ..
// .
// ||||||||||||||||||||||||||||||||||||||||||| // |||||||||||||||||
if ( iBars( NULL, PERIOD_H1 ) // .TEST
!= aCallLockPTR
){
aGreenBoxWINDOWs_UpdateJusTheLiveOne(); // .UPD GUI
aCallLockPTR = iBars( NULL, PERIOD_H1 ); // .SET PTR
}
else {// ///////////////////////////////////// // .UPD GUI in .id=1
// in case LowestLow or HighestHigh inside the Live part of
// aGreenBOX "aGreenBOX.id=1"
// was moved:
// aGreenBoxWINDOW_UpdateJustTheLiveOne();
// re-lock Hi/Lo_LOCKs // .UPD LOCKs
}
}
void aGreenBoxWINDOWs_Update(){
int static aGreenBoxWindow_Duration_SECs = aGreenBoxWindow_HOURs_WIDE
* PeriodSeconds( PERIOD_H1 );
int aGreenBoxWindow_H1Offset_ENDs = TimeHour( TimeCurrent() )
- aGreenBoxWindow_HOUR__ENDs;
if ( aGreenBoxWindow_H1Offset_ENDs < 0 ){
aGreenBoxWindow_H1Offset_ENDs+= 24;
}
datetime aGreenBoxWindow_DATETIME_ENDs = iTime( NULL,
PERIOD_D1,
0
)
+ aGreenBoxWindow_HOUR__ENDs
* PeriodSeconds( PERIOD_H1 );
if ( aGreenBoxWindow_DATETIME_ENDs
- aGreenBoxWindow_Duration_SECs > iTime( NULL,
PERIOD_H1,
0
)
){
aGreenBoxWindow_DATETIME_ENDs = iTime( NULL,
PERIOD_D1,
1
)
+ aGreenBoxWindow_HOUR__END
* PeriodSeconds( PERIOD_H1 );
}
for (
//----------------------------------------------- // --------------------
int anObjIDX = 1, // loop-pre-setting(s)
string anObjNAME = anObjNamePREFIX + "1", // var(s)=value(s) ( life-span only "inside" for(){...}-constructor in MQL4.5+ ...)
int anObjENDs = aGreenBoxWindow_DATETIME_ENDs;
//----------------------------------------------- // --------------------
anObjIDX <= aGreenBoxWindow_nDAYs_BACK; // loop-pre-condition
//----------------------------------------------- // --------------------
// loop-post-update(s)
anObjIDX++, // IDX
anObjNAME = anObjNamePREFIX + anObjIDX, // NAME
anObjENDs = iTime( NULL, // ENDs
PERIOD_D1,
anObjIDX
)
+ PeriodSeconds( PERIOD_H1 )
* aGreenBoxWindow_HOUR__ENDs,
aGreenBoxWindow_H1Offset_ENDs+= 24 // ENDs ^H1
//----------------------------------------------- // --------------------
){ // loop-body:
if ( ObjectFind( anObjNAME ) < 0 ){ // !found .ADD
ObjectCreate( anObjNAME, OBJ_RECTANGLE, 0,
aGreenBoxWindow_DATETIME_ENDs,
iHigh( NULL,
PERIOD_H1,
iHighest( NULL,
PERIOD_H1,
MODE_HIGH,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
),
aGreenBoxWindow_DATETIME_ENDs
- aGreenBoxWindow_Duration_SECs,
iLow( NULL,
PERIOD_H1,
iLowest( NULL,
PERIOD_H1,
MODE_LOW,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
)
);
ObjectSet( anObjNAME, OBJPROP_COLOR, DarkGreen );
ObjectSet( anObjNAME, OBJPROP_BACK, True );
}
else { // found .UPD
ObjectMove( anObjNAME, 0,
aGreenBoxWindow_DATETIME_ENDs,
iHigh( NULL,
PERIOD_H1,
iHighest( NULL,
PERIOD_H1,
MODE_HIGH,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
)
);
ObjectMove( anObjNAME, 1,
aGreenBoxWindow_DATETIME_ENDs
- aGreenBoxWindow_Duration_SECs,
iLow( NULL,
PERIOD_H1,
iLowest( NULL,
PERIOD_H1,
MODE_LOW,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
)
);
ObjectSet( anObjNAME, OBJPROP_COLOR, DarkGreen );
ObjectSet( anObjNAME, OBJPROP_BACK, True );
}
}
}