我的目标是在图表上创建一个矩形对象,从指定时间范围内的最高高点和最低低点测量X
几天?
我知道如何为图表创建一个对象,但我不确定如何让它重复X
几天。我怎样才能做到这一点?我在想也许 For 循环会是一个好方法?我可以使用一些指导。
我的目标是在图表上创建一个矩形对象,从指定时间范围内的最高高点和最低低点测量X
几天?
我知道如何为图表创建一个对象,但我不确定如何让它重复X
几天。我怎样才能做到这一点?我在想也许 For 循环会是一个好方法?我可以使用一些指导。
试试这个代码(专家顾问)。好的,它效率不高(因为它重新计算每个刻度),但我很好地展示了这个概念。
这是它的代码:
//+------------------------------------------------------------------+
//| 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。值得注意的是,extern
如果您的 GUI 层应用程序变得更加智能和复杂,并且如果它直接与XTO接口(例如X ecute - Trade - Operation (s)),构造函数是危险的。
#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=";
对于基于 MT4 的实时增强交易服务,其中 XTO 操作自动绑定/挂钩到某些 GUI 层元素(-triade的可视化部分),必须避免构造函数绑定变量,因为其价值的任何变化(由于MT4架构设计)都会导致实时增强服务的模型和控制器部分发生重置和不可重入冲突,并且此类交易服务将对使用和 XTO。M
V
C
extern
extern
没有-s的增强交易服务的参数化为了实时操作的增强交易服务,有更好(和更安全)的方法来避免extern
对正在运行的服务的破坏性影响。除了其他我最喜欢使用进程到进程/分布式计算消息传递之外,这主要使您的MT4-Terminal 成为基于私有云的交易基础设施内的节点,并且您MQL4
的基于 EA 开始在 Symphonic 管弦乐队中播放,以及其他编排工具(无论是 AI/ML-NeuralNetwork 决策计算过程,还是用于投资组合优化量化模型的基于 GPU 的协方差矩阵评估器,简而言之,这样的任何东西都可以“指导”/“命令”一个MQL4
过程“里面”MT4- 以流畅、不间断和实时、非阻塞、完全异步的方式终端,这听起来是不是很吸引人?是的,它确实!查看这个一次大约 1 [ms] 和更少
一旦您进入 UI 设计领域,您的(最初隐藏的)问题称为 UI 控制循环和整体 UI 响应性(UI 响应您的(MMI
连接器界面)和外部流“的响应速度有多快”输入”(鼠标单击/鼠标移动/鼠标拖放/aMarketEVENT/等)。M
M
I
有必要进行合理的监管,以避免对重复任务的低效调用,这些调用不会给 XTO/MVC 优先/MVC 延迟视觉部分重绘操作带来任何新内容。
尽管 Joseph建议将 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 );
}
}
}