[MT4-EA]对Forex Combo的研究和总结
多年前曾经得到过一个程序叫Forex Combo,曾几何时废寝忘食的不眠不休,为其疯狂,为其如痴如醉。总觉离圣杯仅有一步之遥,那只最后终成空,十年一梦笑其痴。梦醒时又觉不能空做几载。故拿出与诸君共赏。望得同道中人指点一二,或另有所得,但已不如往昔。或不会再为其生,为其死。
forex combo是一套3合一的程序,条件上看短线中线都有。比较适合可以对冲操作的平台。下面是我们按照源码翻译过来的原理,大家可以共赏。
策略一:
buy: 1. 15分钟,前一根k线的wpr (周期18)< -90
2. 15分钟,前1根k线收盘价 > 15分钟前一根k线的smma 60+0.0020
3. 当前的卖出价格 < 15分钟前一k线收盘价+0.0005
止盈:22 止损:100
平仓条件:1. wpr > -13
2. 当前的卖出价格> 15分钟,前一根k线收盘价-0.0005
sell: 1. 15分钟,前一根k线的wpr(周期18) > -10
2. 15分钟,前1根k线收盘价 < 15分钟前一根k线的smma 60-0.0020
3. 当前的卖出价格 > 15分钟前一k线收盘价-0.0005
止盈:22 止损:100
平仓条件:1. wpr < -87
2. 当前的卖出价格 < 15分钟,前一根k线收盘价+0.0005
策略二:
buy: 1. 5分钟,前一根k线的收盘价>=上一小时收盘价-小时线atr(19)*1.4+9*0.0001
止盈:300点 止损:33点 移动止盈:180点
平仓条件:反向信号出现,平仓
sell:1. 5分钟,前一根k线的收盘价<=上一小时收盘价-小时线atr(19)*1.4-9*0.0001
止盈:300点 止损:33点 移动止盈:180点
平仓条件:反向信号出现,平仓
开仓时间:0:00, 2:00, 3:00,6:00,7:00,8:00,9:00,13:00,14:00,17:00,18:00
对应北京时间:8:00,10:00,11:00, 14:00, 15:00, 16:00, 17:00, 21:00, 22:00, 1:00 , 2:00
策略三:
buy: 1. 小时线,boll(26) 上轨-下轨 > 0.0030
2. 小时线,前一根k线最低价 >= boll(26,h1)-3*0.0001
3. 平台时间:22:00-0:00
止盈:170 止损:70 移动止盈:60
平仓条件:反向信号出现平仓(在限定时间内,过时失效)
sell:1. 小时线,boll(26) 上轨-下轨 > 0.0030
2. 小时线,前一根k线最低价 <= boll(26,h1)+3*0.0001
3. 平台时间:22:00-0:00
止盈:170 止损:70 移动止盈:60
平仓条件:反向信号出现平仓(在限定时间内,过时失效)
2楼
运行的货币:EURUSD (貌似最新版有GBPUSD)一般使用于EURUSD
时间周期:5M
这个EA是有三种模式里面,我们都可以从它的参数得知这个EA拥有的模式。
extern bool Use_FXCOMBO_Scalping = TRUE;//剥头皮
extern bool Use_FXCOMBO_Breakout = TRUE;//趋势突破
extern bool Use_FXCOMBO_Reversal = TRUE;//逆势交易
EA给三种模式都设置了开关,给客户提供了方便的接口,可以单模式进行优化测试,的确很方便
extern bool Use_ECN_Broker = FALSE;//ECN平台的开关。
//ECN打开的话,下的订单都是没有止损止盈,都是从代码来实现的。
//三种模式的下单注释
extern string CommentSys1 = "==== 1 ====";
extern string CommentSys2 = "==== 2 ====";
extern string CommentSys3 = "==== 3 ====";
//三种模式的标识符
extern int Magic1 = 111;
extern int Magic2 = 222;
extern int Magic3 = 333;
//使用的最大点差
extern double MaxSPREAD = 4.0;
//下单的滑点
extern int Slippage = 2;
//自动判断时区(自动获取只有在不是测试模式下并且Auto是TRUE的情况)
extern bool AutoGMT_Offset = TRUE;
extern int GMT_Offset_TestMode = 2;//AutoGMT_Offset = FALSE的时候,GMT就由这个参数来设定
//是否采用有风险的资金管理(亏损加仓)
extern bool UseAgresiveMM = FALSE;
接下来是三种模式的资金管理(亏损加仓)设置
extern string MMSys1 = "==== FXCOMBO Scalping MM Parameters ====";
extern double LotsSys1 = 0.1;
extern double TradeMMSys1 = 0.0;
extern double LossFactorSys1 = 2.0;
int gi_196 = 0;
int gi_200 = 2;
int gi_204 = 0;
extern string MMSys2 = "==== FXCOMBO Breakout MM Parameters ====";
extern double LotsSys2 = 0.1;
extern double TradeMMSys2 = 0.0;
extern double LossFactorSys2 = 2.0;
int gi_240 = 0;
int gi_244 = 2;
int gi_248 = 0;
extern string MMSys3 = "==== FXCOMBO Reversal MM Parameters ====";
extern double LotsSys3 = 0.1;
extern double TradeMMSys3 = 0.0;
extern double LossFactorSys3 = 2.0;
int gi_284 = 0;
int gi_288 = 2;
int gi_292 = 0;
从上面我们可以看出三种模式都拥有6个参数。可以判断的是,三个模式的这6个参数的意义是一样的,并且最后三个参数已经写死了的。就是没有提供外部参数让客户改
我们接分析这6个参数具体意义
我们来看一下第一个参数LotsSys(我以LotsSys1为例子),我寻找一下有关于它的代码:我标注了一下。
if (LotsSys1 != 0.0) {
/在LotsSys1和货币允许的最小最大手数之间通过MAX和MIN来获取合法的手数
l_lots_392 = MathMin(g_maxlot_564, MathMax(g_minlot_556,LotsSys1));
if (TradeMMSys1 > 0.0) l_lots_392 = MathMax(g_minlot_556, MathMin(g_maxlot_564, NormalizeDouble(CalcTradeMMSys1() 100.0 * AccountFreeMargin() g_minlot_556 (g_lotsize_576 100), 0) * g_minlot_556));
…………
…………
}
不难的看出,LotsSys1\2\3是三种模式的手数设定,在它下面还看到TradeMMSys这个参数的使用。
接着看看TradeMMSys这个参数:
if (TradeMMSys1 > 0.0) l_lots_392 = MathMax(g_minlot_556, MathMin(g_maxlot_564, NormalizeDouble(CalcTradeMMSys1() 100.0 * AccountFreeMargin() g_minlot_556 (g_lotsize_576 100), 0) * g_minlot_556));
从这句代码里面,我们可以看到一个函数CalcTradeMMSys1()
double CalcTradeMMSys1() {
int li_8;
double ld_16;
double ld_ret_0 = TradeMMSys1;
int li_12 = 0;
if (Digits <= 3) ld_16 = 0.01;
else ld_16 = 0.0001;
// 这个FOR循环,有意思,li_12记录着连续亏损的订单数量,gi_204这个参数也是6个参数之一,在这里大致的作用起一个盈利目标的作用
for (int l_hist_total_24 = OrdersHistoryTotal(); l_hist_total_24 >= 0; l_hist_total_24--) {//注意是订单的历史记录
if (OrderSelect(l_hist_total_24, SELECT_BY_POS, MODE_HISTORY)) {
if (OrderType() <= OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == Magic1) {
if (OrderProfit() > 0.0) {
if (gi_204 == 0) break;
if (MathAbs(OrderClosePrice() - OrderOpenPrice()) ld_16 > gi_204) break;//符合盈利目标就跳出循环
} else li_12++;
}
}
}
//gi_196(默认是0),gi_200(默认是2),LossFactorSys1(默认是2.0) 这三个都是6个参数之一,这样一来我们就找到这个6个参数的所在地方了。
//不难看出呀,gi_196是连续亏损的参数设置,gi_200是用来计算幂
if (li_12 > gi_196 && gi_200 > 1) {
/大概的意思是:如果连续亏损次数>gi_196设定的次数并且设定gi_200大于1那么进入控制语句里面去
li_8 = MathMod(li_12, gi_200);
//求得 li_12除以gi_200 的余数.按照默认的情况li_8有可能的结果为0,1
ld_ret_0 *= MathPow(LossFactorSys1, li_8);
//通过计算得到li_8,用来做幂,底数为LossFactorSys1,返回的结果也有只有两种1,或者LossFactorSys1的值。这里还没完
//MathPow()得到的结果还需要与ld_ret_0相乘。ld_ret_0的值现在的情况应该是等于0, TradeMMSys1 就是ld_ret_0初始化时候的值.
}
if (MMMax > 0.0 && ld_ret_0 > MMMax) ld_ret_0 = MMMax;
/通过上面的计算还没完,得判断一下最后的结果是否在最大的允许范围内。超过就等于最大的,然后下面返回它的值
return (ld_ret_0);
}
这个函数用到了6个参数中的5个参数,其中有3个是官方不提供外部参数的,看来是过于复杂,担心客户接受不了还是什么的。
接着返回到函数调用处:(我们通过一个例子来计算一下)
AccountFreeMargin 为 500
g_minlot_556 这个变量是货币的最小的手数 0.1
g_lotsize_576 这个是1个标准手数大小 10W
TradeMMSys1 = 1;默认为0,0的话无法启动这个亏损加仓机制,所以我们给它1,其他的参数的数值不改变
li_12 = 2;假设连续亏损2次
li_8 得到的结果 0
MathPow(LossFactorSys1,li_8) 得到结果 1
ld_ret_0 最后结果 1 并且小于 MMMax 那返回去
CalcTradeMMSys1() 函数得到的结果应该为 1
CalcTradeMMSys1() 100.0 * AccountFreeMargin() g_minlot_556 (g_lotsize_576 100)进入代入:
1/100*500/0.1/(100000/100)=0.05
可是NormalizeDouble(0.05,0)结果是为0的。
MathMax(g_minlot_556, 0)就用最小手数0.1来下单了。证明在这个机制的情况,加仓的风险还是比较低比较安全的。
但如果要体现它这个资金管理是否合理,我们就需要大胆的改一下了:
AccountFreeMargin 为 10000
TradeMMSys1 = 3;
LossFactorSys1 = 3.0;
li_12 = 3 连续亏损3次
li_8 得到的结果 1
MathPow(LossFactorSys1,li_8) 得到结果 3
ld_ret_0 = 9.0 代入代码中 不详解
CalcTradeMMSys1() = 9.0
9/100*10000/0.1/1000 = 9.0
NormalizeDouble(9.0,0)结果是为9
当然不可能是9手,后面还需要乘以0.1,之前因为等于0,所以没说需要NormailzeDouble的结果还需要乘以0.1
所以最后需要下的手数为0.9手
这个资金管理还是很周密的,如果有需要用到的话,根本可以提取代码。
通过保证金以及连续亏损次数得到一个适合自己的手数。真不错。
通过观察,我们现在就知道了这6个参数的作用。没有提供外部参数的3个参数要修改的话真的看你的需要了。毕竟这是少部分人。
韬客社区www.talkfx.co
3楼
接着讲Forex Combo 1.46…… 睡不着还是来写完它比较踏实。这我认为是个不错的EA
上一次已经讲完它MM Parameters的参数作用以及前面参数的作用。
extern string CommonMM = "==== Main MM Parameters ====";extern double MMMax = 20.0;extern double MaximalLots = 50.0;
Main固然汉义过来是主要的意思。来看看这两个参数作用。
MMMax出现的代码处:
回顾上一遍的CalcTradeMMSys1\2\3函数,在这里的末尾都有出现:
if (MMMax > 0.0 && ld_ret_0 > MMMax) ld_ret_0 = MMMax;
作用很明显主要来限制CalcTradeMMSys返回的最大值。如果大于MMMax就返回MMMaxMaximalLots出现的代码处: if (l_lots_392 > MaximalLots) l_lots_392 = MaximalLots;l_lots_392变量是下单的手数,大概的作用也就是用于限制最大的下单手数。这两个参数都是最基础,但是也是三种模式都共用的,所以才是主要资金管理参数的原因吧。 到下面的都是三种模式交易的参数:System Parametersextern string Scalping = "==== FXCOMBO Scalping System Parameters ====";extern int StopLoss = 300;extern int TakeProfit = 21;int g_period_336 = 60;extern int TREND_STR = 20;int g_period_344 = 18;extern int OSC_open = 10;extern int OSC_close = 13;int gi_356 = -5;int gi_360 = 21;int gi_unused_364 = 21;int gi_368 = 6;
StopLoss与TakeProfit:设置止损和止盈这个没什么疑问
g_period_336 = 60:这个参数也没有提供外部参数,那么我们看看这个参数出现的代码处
double l_ima_100 = iMA(NULL, PERIOD_M15, g_period_336, 0, MODE_SMMA, PRICE_CLOSE, 1);
大家需要根据自己的代码来看来搜索,有可能反编译的变量名不一样,但如果出处一样这些的变量名称应该是一样。
大概看了一下 l_ima_100 是它用于判断交易值之一,g_period_336,是设置其均线周期。
TREND_STR:部分代码
double l_iclose_92 = iClose(NULL, PERIOD_M15, 1);
if (Digits <= 3) ld_40 = 0.01;
else ld_40 = 0.0001;
l_iclose_92 > l_ima_100 + TREND_STR * ld_40
判断前一根柱子的收盘价是否在均线值+TREND_STR的上面
由于代码太多,不太方便粘贴,只能在这里粗略的说说。大家应该看得懂这些参数的用意。
g_period_344这个参数没有提供外部参数,看看出现的代码处
double l_iwpr_108 = iWPR(NULL, PERIOD_M15, g_period_344, 1);
if (l_iwpr_108 > (-OSC_close) && Bid > l_iclose_92 + gi_356 * ld_40)
这是wpr的周期设置,顺便查看一下应用108变量的地方,这里还出现了OSC_close的变量。
OSC_open、OSC_close:
l_iwpr_108 < OSC_open + (-100)
联系一下上文就可以知道其参数的意义。
gi_356出现的代码段:也是交易条件之一
Bid > l_iclose_92 + gi_356 * ld_40
Bid < l_iclose_92 - gi_356 * ld_40
gi_360 出现的代码段:
int li_196 = gi_360 + li_48;
li_48是值是时区;gi_360看来跟时间有关系。
gi_unused_364 没有被使用过的痕迹,估计写多了的。
gi_368出现的代码处:
l_iwpr_108 < gi_368 +(-100)
这样分散来看,只能看出这些变量的定义和使用地方,还不能完全看出系统的交易方法。但这很有用。我们开始去交易的地方看看。
下面是买单的交易条件:
if (l_count_256 < 1 && (l_iclose_92 > l_ima_100 + TREND_STR * ld_40 && l_iwpr_108 < OSC_open + (-100) && Bid < l_iclose_92 - gi_356 * ld_40) || (l_iwpr_108 < gi_368 +
(-100) && Bid < l_iclose_92 - gi_356 * ld_40 && Hour() == li_196 || Hour() == li_200)) {
ls_400 = "BUY";
l_cmd_28 = 0;
l_color_24 = Aqua;
RefreshRates();
l_price_0 = NormalizeDouble(Ask, Digits);
l_price_8 = l_price_0 - StopLoss * ld_40;
l_price_16 = l_price_0 + TakeProfit * ld_40;
}
下面是卖单条件:
if (l_count_260 < 1 && (l_iclose_92 < l_ima_100 - TREND_STR * ld_40 && l_iwpr_108 > (-OSC_open) && Bid > l_iclose_92 + gi_356 * ld_40) || (l_iwpr_108 > (-gi_368) &&
Bid > l_iclose_92 + gi_356 * ld_40 && Hour() == li_196 || Hour() == li_200)) {
ls_400 = "SELL";
l_cmd_28 = 1;
l_color_24 = Red;
RefreshRates();
l_price_0 = NormalizeDouble(Bid, Digits);
l_price_8 = l_price_0 + StopLoss * ld_40;
l_price_16 = l_price_0 - TakeProfit * ld_40;
}
在结合我们上面变量,大概应该可以知道Scalping交易的条件。
韬客社区www.talkfx.co
4楼
还是ForexCombo进行分析,依旧是它的Scalping模式,这个模式应该是三个模式中最好的,那么就值得大家去借鉴了。无数的借鉴这让你的EA更上一层楼。好的,我们进入主题,在二的笔记中,我截取了两段较长的代码,两段代码也是这个模式的主要交易代码,可能有些朋友是懂非懂的不知道这些代码的具体意义,于是我们又再详细了一下代码:
if (l_count_256 < 1 && (l_iclose_92 > l_ima_100 + TREND_STR * ld_40 && l_iwpr_108 < OSC_open + (-100) && Bid < l_iclose_92 - gi_356 * ld_40) || (l_iwpr_108 < gi_368 +
(-100) && Bid < l_iclose_92 - gi_356 * ld_40 && Hour() == li_196 || Hour() == li_200))
我们进行中文简述:
//MAGIC1订单数<1并且(前一根K线收盘价大于均线+TRENDSTR的值并且WPR指标小于OSC_OPEN-100并且现在的买价小于收盘价减去-5就是加上5)或者是
//WPR指标小于gi_368-100并且买价小于收盘价-gi_356并且现在是交易的时间范围
可以看出,要交易的话有两种情况存在。
第一种:
(前一根K线收盘价大于均线+TRENDSTR的值并且WPR指标小于OSC_OPEN-100并且现在的买价小于收盘价减去-5就是加上5)
第二种:
WPR指标小于gi_368-100并且买价小于收盘价-gi_356并且现在是交易的时间范围
&& Hour() == li_196 || Hour() == li_200
li_196和li_200的代码:
int gi_360 = 21;
int li_196 = gi_360 + li_48;
int li_200 = gi_360 + li_48;
这个应该是限制交易的小时数。我们不妨测试一下。默认参数的话,大概是什么时间里交易。也可以通过计算得到li_196和li_200的值。
从表达式上看,我们可以知道li_196和li_200是一样的,那么我们计算li_196的值。
li_48 = -9;
li_196 = 12;
也就是当小时数为12的时候,又符合WPR指标小于gi_368-100并且买价小于收盘价-gi_356
那么第二种交易就触发,我们大可改这个条件,甚至删除来测试这个条件对我们创造的盈利到底有多少。
接着我们看看卖单,它的条件又是如何的:
if (l_count_260 < 1 && (l_iclose_92 < l_ima_100 - TREND_STR * ld_40 && l_iwpr_108 > (-OSC_open) && Bid > l_iclose_92 + gi_356 * ld_40) || (l_iwpr_108 > (-gi_368) &&
Bid > l_iclose_92 + gi_356 * ld_40 && Hour() == li_196 || Hour() == li_200))
可以看到的与买单相反,这里不做过多的详细的讲解了。可以肯定的是,这个交易条件的成功率很高。那么我们可以占为己有。
看完Scalping的开单条件,那我们还需要来研究它的Close条件,Scalping不是靠止损和止盈,在回测的时候就可以看到它有Close事件,我们找找代码。
if (OrderMagicNumber() == Magic1) {
if (OrderType() == OP_BUY) {
if (OrderStopLoss() == 0.0) {
l_price_312 = NormalizeDouble(Ask - StopLoss * ld_40, Digits);
l_price_320 = NormalizeDouble(Ask + TakeProfit * ld_40, Digits);
if (CheckStop(OrderType(), l_price_312) && CheckTarget(OrderType(), l_price_320)) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_312, l_price_320, 0, Green);
}
if (l_iwpr_108 > (-OSC_close) && Bid > l_iclose_92 + gi_356 * ld_40) {
RefreshRates();
OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Bid, Digits), Slippage, Violet);
} else l_count_256++;
} else {
if (OrderStopLoss() == 0.0) {
l_price_312 = NormalizeDouble(Bid + StopLoss * ld_40, Digits);
l_price_320 = NormalizeDouble(Bid - TakeProfit * ld_40, Digits);
if (CheckStop(OrderType(), l_price_312) && CheckTarget(OrderType(), l_price_320)) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_312, l_price_320, 0, Green);
}
if (l_iwpr_108 < OSC_close + (-100) && Bid < l_iclose_92 - gi_356 * ld_40) {
RefreshRates();
OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Ask, Digits), Slippage, Violet);
} else l_count_260++;
}
}
这段代码是它的平仓机制了。我们进行分析一下。
if (OrderType() == OP_BUY) {
if (OrderStopLoss() == 0.0) {
l_price_312 = NormalizeDouble(Ask - StopLoss * ld_40, Digits);
l_price_320 = NormalizeDouble(Ask + TakeProfit * ld_40, Digits);
if (CheckStop(OrderType(), l_price_312) && CheckTarget(OrderType(), l_price_320)) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_312, l_price_320, 0, Green);
}
这一段代码,是用来判断订单是否有止损止盈,没有的话,更改一下。
if (l_iwpr_108 > (-OSC_close) && Bid > l_iclose_92 + gi_356 * ld_40) {
RefreshRates();
OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Bid, Digits), Slippage, Violet);
}
这一段是平单的代码,这是买单的平单代码,wpr指标的>-OSC_close并且,买价大于前一根K线收盘价+gi_356个点的话,买单则平单。OSC_close在这里是13,大概这个平单条件比较轻重于WPR指标,如果WPR指标在-13上面,基本是一个超卖区,那么这时候就平掉多单。l_count_256是用来记录现在MAGIC1的买单数量的。
那么现在我们在来看看,卖单的平单代码:
if (OrderStopLoss() == 0.0) {
l_price_312 = NormalizeDouble(Bid + StopLoss * ld_40, Digits);
l_price_320 = NormalizeDouble(Bid - TakeProfit * ld_40, Digits);
if (CheckStop(OrderType(), l_price_312) && CheckTarget(OrderType(), l_price_320)) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_312, l_price_320, 0, Green);
}
上面这一段跟买单一样,判断是否没有设置止损,没有的话,设置止损。
if (l_iwpr_108 < OSC_close + (-100) && Bid < l_iclose_92 - gi_356 * ld_40) {
RefreshRates();
OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Ask, Digits), Slippage, Violet);
} else l_count_260++;
如果WPR指标小于13+(-100)=-87,WPR进入超买区,并且买价小于前一根K线收盘价+5点这样的话,我们就平单。否则卖单数量记录++
到此我们可以知道其实模式一,Scalping这个的开单可能相对用到MA和WPR然后平单用到WPR,其他也没什么特别的指标,然后就价位的限制,可以说它的交易条件是相当的简单。
大家大可用Scalping这个模式测试一下,10年的交易情况如何。
5楼
进行ForexCombo的模式二,BreakOut,趋势突破策略,我们就来看看吧,我先用我们一个EXCEL回测数据工具记录了一下在回测过程,一些重要的数据,这个模式二,2011年走的让人忐忑丫,或者说这个模式本来就很让人忐忑,30点的止损,可以接连好几次的亏损,个人觉得这个模式还得优化一下阿。看看它的参数吧。
extern string Breakout = "==== FXCOMBO Breakout System Parameters ====";
extern int TakeProfit_II = 500;
extern int StopLoss_II = 30;
extern int MaxPipsTrailing2 = 180;
extern int MinPipsTrailing2 = 10;
extern int Break = 13;
int g_period_400 = 1;
int g_period_404 = 19;
double gd_408 = 1.4;
extern double ATRTrailingFactor2 = 4.7;
int gi_424 = 300;
int gi_428 = 270;
int gi_432 = 20;
int gi_436 = 0;
int gi_440 = 8;
int gi_444 = 7;
int gi_448 = 18;
int gi_452 = 17;
int gi_456 = 13;
int gi_460 = 14;
int gi_464 = 6;
int gi_468 = 9;
int gi_472 = 2;
int gi_476 = 3;
它的参数挺多的,我们看看这些参数具体是被什么指标或者表达式所应用。
extern int TakeProfit_II = 500;
extern int StopLoss_II = 30;
该模式的止盈500点和止损30点。显而易见的参数。下面是它根据ATR通道的移动止损参数,我把这3个相关的参数贴出来
extern int MaxPipsTrailing2 = 180;
extern int MinPipsTrailing2 = 10;
extern double ATRTrailingFactor2 = 4.7;
代码可见:
if (TimeCurrent() >= li_284) {
ld_344 = l_iatr_116 * ATRTrailingFactor2;
if (ld_344 > MaxPipsTrailing2 * ld_40) ld_344 = MaxPipsTrailing2 * ld_40;
if (ld_344 < MinPipsTrailing2 * ld_40) ld_344 = MinPipsTrailing2 * ld_40;
if (Bid - OrderOpenPrice() > gi_428 * ld_40) ld_344 = gi_432 * ld_40;
l_price_352 = NormalizeDouble(Bid - ld_344, Digits);
if (Bid - OrderOpenPrice() > ld_344) {
if (OrderStopLoss() < l_price_352 && CheckStop(OrderType(), l_price_352)) {
l_bool_32 = OrderModify(OrderTicket(), OrderOpenPrice(), l_price_352, OrderTakeProfit(), 0, Blue);
if (l_bool_32) {
l_datetime_280 = TimeCurrent();
g_datetime_584 = l_datetime_280;
}
}
}
}
double l_iatr_116 = iATR(NULL, PERIOD_H1, g_period_404, 1);
g_period_404 是我们上面参数的之一,它的默认是19.
通过计算我们可以大概猜出l_iatr_116的Max的话应该38或以上,Min应该是2左右。那么ATR有多少时间点是出现这样的情况呢,大家可以回测然后找位置看看,这里不是开单这里移动止损。
if (Bid - OrderOpenPrice() > gi_428 * ld_40) ld_344 = gi_432 * ld_40;
gi_428 = 270 上面的参数设置的,gi_432 =20。这上面这句比较简单大概是盈利270点的话,那就ld_344=20点
if (ld_344 > MaxPipsTrailing2 * ld_40) ld_344 = MaxPipsTrailing2 * ld_40;
if (ld_344 < MinPipsTrailing2 * ld_40) ld_344 = MinPipsTrailing2 * ld_40;
这另外两种获取止损位的计算方法,也比较简单,如果ATR在38以上则新的止损在Bid-MaxPipsTrailing2*ld_40,类似。如果在2以下则新的止损位在Bid-MinPipsTrailing2
大概就将移动止损的参数讲完了。大家自己去体会。接着往下看Break=13这个参数它的代码出处:
if (l_iclose_148 <= ld_140 - Break * ld_40) {
RefreshRates();
OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Bid, Digits), Slippage, Violet);
} else l_count_264++;
double l_iclose_148 = iClose(NULL, PERIOD_M5, 1);
double ld_140 = l_ima_124 - l_iatr_116 * gd_408;
double gd_408 = 1.4; 这是上面的参数设置之一,也是没有提供外部接口的参数
double l_ima_124 = iMA(NULL, PERIOD_H1, g_period_400, 0, MODE_EMA, PRICE_CLOSE, 1);
double l_iatr_116 = iATR(NULL, PERIOD_H1, g_period_404, 1);
g_period_404\g_period_400\gd_408这3个上面的变量都用到了。得代入进去。
这里的原理构成了一个以H1为主的通道。如果5分钟的收盘价跌破了前一个小时的通道下轨,那么就确定下降趋势已经形成。。
这时候平单离场,到现在为止有提供extern外部参数的变量基本都是平单或者移动止损的参数,仿佛没有开单的外部参数可以设置当然排除止损止盈。那么我们看看这个模式的开单条件是如何。。
if (l_count_268 < 1 && l_iclose_148 <= ld_140 - Break * ld_40) {
ls_400 = "SELL";
l_cmd_28 = 1;
l_color_24 = Yellow;
l_price_0 = NormalizeDouble(Bid, Digits);
l_price_8 = l_price_0 + StopLoss_II * ld_40;
l_price_16 = l_price_0 - TakeProfit_II * ld_40;
}
if (l_count_264 < 1 && l_iclose_148 >= ld_132 + Break * ld_40) {
ls_400 = "BUY";
l_cmd_28 = 0;
l_color_24 = DodgerBlue;
l_price_0 = NormalizeDouble(Ask, Digits);
l_price_8 = l_price_0 - StopLoss_II * ld_40;
l_price_16 = l_price_0 + TakeProfit_II * ld_40;
}
ForexCombo写的真的很规范很工整,非常喜欢。
我们拿卖单的条件来说事: if (l_count_268 < 1 && l_iclose_148 <= ld_140 - Break * ld_40)
l_count_268 这个Magic2的买单数量。
l_iclose_148 前一根K线的5分钟收盘价
看到这里我们应该明白了吧,这不是买单的平仓条件吗?
5分钟的K线的收盘价,抵触1小时的通道,平多开空。大家可以将这个通道给写出来。这应该没什么难题。
发现下面还有很多的参数没有讲到模式二已经讲得差不多了,我们具体去找找每个变量用到的地方。
gi_424 = 300;
int li_284 = g_datetime_584 + gi_424;
这个是OrderModify的间隔单位是秒。300秒,也就是OrderModify每5分钟修改一次止损。而不是不停的修改。这种好坏各占多少呢。
int li_212 = gi_436 + li_48;
int li_216 = gi_440 + li_48;
int li_220 = gi_444 + li_48;
int li_224 = gi_448 + li_48;
int li_228 = gi_452 + li_48;
int li_232 = gi_456 + li_48;
int li_236 = gi_460 + li_48;
int li_240 = gi_464 + li_48;
int li_244 = gi_468 + li_48;
int li_248 = gi_472 + li_48;
int li_252 = gi_476 + li_48;
if (li_212 > 23) li_212 -= 24;
if (li_212 < 0) li_212 += 24;
if (li_216 > 23) li_216 -= 24;
if (li_216 < 0) li_216 += 24;
if (li_220 > 23) li_220 -= 24;
if (li_220 < 0) li_220 += 24;
if (li_224 > 23) li_224 -= 24;
if (li_224 < 0) li_224 += 24;
if (li_228 > 23) li_228 -= 24;
if (li_228 < 0) li_228 += 24;
if (li_232 > 23) li_232 -= 24;
if (li_232 < 0) li_232 += 24;
if (li_236 > 23) li_236 -= 24;
if (li_236 < 0) li_236 += 24;
if (li_240 > 23) li_240 -= 24;
if (li_240 < 0) li_240 += 24;
if (li_244 > 23) li_244 -= 24;
if (li_244 < 0) li_244 += 24;
if (li_248 > 23) li_248 -= 24;
if (li_248 < 0) li_248 += 24;
if (li_252 > 23) li_252 -= 24;
if (li_252 < 0) li_252 += 24;
这个很显然的东西阿。又是计算交易的小时数。
if (!(TimeHour(TimeCurrent()) != li_212 && TimeHour(TimeCurrent()) != li_216 && TimeHour(TimeCurrent()) != li_220 && TimeHour(TimeCurrent()) != li_224 && TimeHour(TimeCurrent()) != li_228 &&
TimeHour(TimeCurrent()) != li_232 && TimeHour(TimeCurrent()) != li_236 && TimeHour(TimeCurrent()) != li_240 && TimeHour(TimeCurrent()) != li_244 && TimeHour(TimeCurrent()) != li_248) ||
!(TimeHour(TimeCurrent()) != li_252)) {
看来在很多的小时数,这个模式都被限制了交易。这种写法还挺怪异的,实际可以写的很明了,这里给人错觉是不等于才可以交易,实际是必须在我们得到的小时数里交易。
}
我这边的数据是:1、3、4、7、8、9、10、14、15、18、19
这个测试一下就知道了。
这个模式得优化呀。。。。
通过我们的工具,知道它,耗费了很多很好的盈利。比如一个订单最大获利过211点,但是平单的时候只有111点盈利。然后还有更离谱的,99点的盈利最后亏损平单。真是瞎了。很多的订单的都可以成功获利的。
6楼
继续探讨一下,模式二,我将继续分享。
为此,我尝试将1H的通道构造出来。这个通道包含着它如何开仓,平仓的原理,可是肉眼看不见,这是件烦人的事情。于是决定给FOREX COMBO 制作其交易原理的指标,使大家能一目了然。如图:
看到这幅图,大概就知道模式二的交易原理了吧,所以说,非常简单,虽然不说盈利能力很强,但是真的有效果的。再利用我们的工具回测里面,30点止损,可是有很多的订单都曾经获得几十以上的盈利,只是它移动止损机制,无法及时捕获盈利,所以导致看上很坎坷。
看完模式2的我们返回去看看模式1的交易图又是怎样的。模式1相对模式2要繁杂多了。自己写了2个辅助指标帮盘面更加清晰:
下单时间 2011.12.21 06:30 EURUSD 买 0.1 1.3106 1.2956 1.3127
这里符合三个要素:WPR指标,轨道之上,现价>前一根K线收盘价N点,进场做多单,这是一个漂亮的多单。这是模式2近一年的两种情况的测试,一个没有参数优化,一个是优化过后的。
韬客社区www.talkfx.co
7楼
已经研究了前面的两个模式,继续完成第三模式的研究,Reversal模式,列出它相关的参数:
extern int BegHourSys_III = 22;
extern int EndHourSys_III = 0;
extern double TakeProfit_III = 160.0;
extern int StopLoss_III = 70;
int gi_508 = 300;
extern int MaxPipsTrailing3 = 60;
extern int MinPipsTrailing3 = 20;
int g_period_520 = 60;
double gd_524 = 13.0;
int g_period_532 = 26;
int gi_536 = -3;
int gi_540 = 30;
bool gi_544 = TRUE;
string gs_548 = "";
double g_minlot_556 = 0.0;
double g_maxlot_564 = 0.0;
int g_leverage_572 = 0;
int g_lotsize_576 = 0;
int g_stoplevel_580 = 0;
int g_datetime_584 = 0;
int g_datetime_588 = 0;
不是extern的,可能有些不是它的参数,因为这是整个EA,全局变量的结尾了,也就是我们的研究已经接近尾声了。
我们先研究下面两个外部参数,并且列出它的代码出现地方:
extern int BegHourSys_III = 22;
extern int EndHourSys_III = 0;
int li_204 = BegHourSys_III + li_48;
int li_208 = EndHourSys_III + li_48;
if (li_204 > 23) li_204 -= 24;
if (li_204 < 0) li_204 += 24;
if (li_208 > 23) li_208 -= 24;
if (li_208 < 0) li_208 += 24;
大概就明白了,这两个参数是限制这个模式所处于的时间段。
用Alert调试一下。
我测试的时候是0、1、2这三个小时数交易
extern double TakeProfit_III = 160.0;
extern int StopLoss_III = 70;
这是这个模式的止损止盈的设置,不进行探讨
int gi_508 = 300;
int li_292 = g_datetime_588 + gi_508;
这个 gi_508 是用来设置移动止损的修改间隔
与模式二的有类似的地方
extern int MaxPipsTrailing3 = 60;
extern int MinPipsTrailing3 = 20;
如果要上面这两个外部参数,把这段贴出来可能更好的去理解它以及还有其他参数:
if (TimeCurrent() >= li_292) {
ld_376 = l_iatr_156 * gd_524;
if (ld_376 > MaxPipsTrailing3 * ld_40) ld_376 = MaxPipsTrailing3 * ld_40;
if (ld_376 < MinPipsTrailing3 * ld_40) ld_376 = MinPipsTrailing3 * ld_40;
l_price_384 = NormalizeDouble(Bid - ld_376, Digits);
if (Bid - OrderOpenPrice() > ld_376) {
if (OrderStopLoss() < l_price_384 && CheckStop(OrderType(), l_price_384)) {
l_bool_36 = OrderModify(OrderTicket(), OrderOpenPrice(), l_price_384, OrderTakeProfit(), 0, Blue);
if (l_bool_36) {
l_datetime_288 = TimeCurrent();
g_datetime_588 = l_datetime_288;
}
}
}
}
double l_iatr_156 = iATR(NULL, PERIOD_M5, g_period_520, 1);
int g_period_520 = 60;
double gd_524 = 13.0;
MaxPipsTrailing3 = 60;
MinPipsTrailing3 = 20;
if (ld_376 > MaxPipsTrailing3 * ld_40) 如果这个条件为真的话那么l_iatr_15>=0.0005的值,它满足这个条件
if (ld_376 < MinPipsTrailing3 * ld_40)如果这个条件为真的话那么l_iatr_156<=0.0001的值,它满足这个条件
MinPipsTrailing应该很难达到了。
这种移动止损模式真的很特别。根据ATR指标来移动止损,用MAX和MIN限制移动的大小。
l_price_384 = NormalizeDouble(Bid - ld_376, Digits)//计算新止损的位置
if (Bid - OrderOpenPrice() > ld_376) //如果买单盈利的点数>ld_376
if (OrderStopLoss() < l_price_384 && CheckStop(OrderType(), l_price_384)) {//毕竟新的止损位>旧的止损位则进行修改止损
if (l_bool_36) {
l_datetime_288 = TimeCurrent();
g_datetime_588 = l_datetime_288;
}
//如果修改成功,则记录当前时间。
它的模式二和模式三是用同样的方式进行移动止损,使用ATR*一个系数,等到移动的点子,然后进行判断移动的点子是不是在合理的范围内,超过了就设定为最大或最小的移动的止损点,然后计算新的止损位置,再判断现在的盈利点是否>这个要移动的止损点,并且新的止损>旧的止损就修改止损。当然模式二它移动止损比模式三就多了一个条件。基本差不多
点评:这个移动止损机制的好坏,要看参数的设置,参数设置的好,才可以充分利用盈利空间,否则将浪费百分50的利润,那就弄巧成拙了。所以调整好这几个参数,反而资金管理参数默认的就可以了,甚至不用都可以。
移动止损分析完,可是还没有涉及到开仓和平仓内容,证明这两部分的参数都被隐藏起来了,FOREXCOMBO看来是只给客户提供修改资金管理和移动止损的接口,除了模式一,基本没有透漏多少的策略,真需要分析代码。
找一下Reversal模式的开仓条件,我所有的笔记都是只讲解BUY或SELL。
if (l_count_272 < 1 && (li_204 <= li_208 && TimeHour(TimeCurrent()) >= li_204 && TimeHour(TimeCurrent()) <= li_208) || (li_204 > li_208 && TimeHour(TimeCurrent()) >= li_204 ||
TimeHour(TimeCurrent()) <= li_208) && l_ibands_180 - l_ibands_188 >= gi_540 * ld_40 && l_ilow_172 < l_ibands_188 - gi_536 * ld_40) {
这个IF条件是BUY单的条件,好长一段代码是限制时间的条件,不解读了。
l_ibands_180 - l_ibands_188 >= gi_540 * ld_40 && l_ilow_172 < l_ibands_188 - gi_536 * ld_40 这是主要的交易条件
double l_ibands_180 = iBands(NULL, PERIOD_H1, g_period_532, 2, 0, PRICE_CLOSE, MODE_UPPER, 1);
double l_ibands_188 = iBands(NULL, PERIOD_H1, g_period_532, 2, 0, PRICE_CLOSE, MODE_LOWER, 1);
int gi_540 = 30;//BOLL的轨道距离
int g_period_532 = 26;//一小时BOLL的周期
l_ilow_172 1小时图的前一根K线的最低价
int gi_536 = -3;
主要是这两个条件了,1小时的26的BOLL规矩>30并且前一根K线的最低价格已经跌破了BOLL下轨-(-3)点
如果gi_536如果越大则越难满足交易条件。
现在我们去寻找其BUY的平仓条件:
if ((li_204 <= li_208 && TimeHour(TimeCurrent()) >= li_204 && TimeHour(TimeCurrent()) <= li_208) || (li_204 > li_208 && TimeHour(TimeCurrent()) >= li_204 || TimeHour(TimeCurrent()) <= li_208) && l_ibands_180 - l_ibands_188 >= gi_540 * ld_40 && l_ihigh_164 > l_ibands_180 + gi_536 * ld_40) {
一样平仓和开仓都必须是在指定的小时数里面
l_ibands_180 - l_ibands_188 >= gi_540 * ld_40 && l_ihigh_164 > l_ibands_180 + gi_536 * ld_40
这才是主要的平仓条件:轨道的距离要>=30并且前一根K线的最高突破上轨+(-3)点
买单的平仓条件也是卖单的开仓条件
卖单的平仓条件也是买单的开仓条件
整个FOREXCOMBO就分析完了。这个EA对通道这玩意用的很多,有自己构造的通道。移动止损方便它特有的ATR的移动止损方法。接着上传一下第三模式的测试图
说真的这个模式不咋滴,1年了折腾的很,如果叫一个人去投资这样的收益率的EA估计他肯定不肯。
发表于:2015-05-26 09:28只看该作者
9楼
看看再说
韬客社区www.talkfx.co
发表于:2015-05-27 01:33只看该作者
10楼
有的时候条件他复杂。满足时往往只有很小的利润空间。。简单粗暴反而能抓住趋势。。。
韬客社区www.talkfx.co
发表于:2015-05-29 01:04只看该作者
11楼
Greeda 发表于 2014-4-9 09:46
运行的货币:EURUSD (貌似最新版有GBPUSD)一般使用于EURUSD 时间周期:5M
韬客社区www.talkfx.co
发表于:2015-07-08 12:14只看该作者
12楼
谢谢分享!!!
韬客社区www.talkfx.co
发表于:2020-12-22 13:15只看该作者
13楼
感謝無私分享
韬客社区www.talkfx.co