double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000)// функция лота
{
//проверка достаточности средств if(deposSize <
MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT))
//для проведения торговли
{
Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом");
return0.0;
}
//проверка, на стоп-аут
ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
double procUsed;
if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах
{
if(proc > AccountInfoDouble(ACCOUNT_MARGIN_SO_SO))
{
Alert("Потеря выше уровня STOPOUT!\nРасчет лота производиться по величине STOPOUT.");
procUsed=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100;
//Print(MarketInfo(currName,MODE_MARGINREQUIRED)," ",procUsed);return deposSize/(pipsLoss+procUsed*MarketInfo(currName,MODE_MARGINREQUIRED));
}
}
//а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах//как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделаетdouble currMove=deposSize*proc/100;// расчет процента от величины депозитаdouble lotCount=currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE));//ну а тут и ведеться сам расчет лотаif(lotCount<MarketInfo(currName,MODE_MINLOT))
{
returnMarketInfo(currName,MODE_MINLOT);
}
if(lotCount>MarketInfo(currName,MODE_MAXLOT))
{
returnMarketInfo(currName,MODE_MAXLOT);
}
returnNormalizeDouble(lotCount,2);
//return lotCount;
}
double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000)
{
double lotCount=0;
//1) проверка достаточности средств для проведения торговли
if(deposSize <
MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT))
{
//Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом");
return 0.0;
}
double currMove=deposSize*proc/100;// расчет процента от величины депозита
//расчивываем максимально допустимый лот, до стоп-аута
double SOlot = deposSize/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE)+
MarketInfo(currName,MODE_MARGINREQUIRED)*AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100);
//расчет величины депозита, при котором сработает стоп-аут
double SOval = SOlot*pipsLoss*MarketInfo(currName,MODE_TICKVALUE);
ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах
{
if((deposSize-currMove)<SOval)//проверяем остаток на депозите на превышение значения стоп-аут
{
if(SOlot<MarketInfo(currName,MODE_MINLOT))//если лот стоп-аута меньше минимального лота
{
lotCount = MarketInfo(currName,MODE_MINLOT);
//находим количесвто пунктов до вылета по стоп-ауту и выбрасываем предупреждение
int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE)));
Print("При прохождении ценой больше ", pipsSO," пп.- \nторговля будет прекращена по STOP OUT!");
}
else//если наш стоп-аут лот больше равно минимального
{
lotCount = SOlot;
int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE)));
Print("Достижение STOP OUT, произойдет через ", pipsSO, " и работа будет проведена с максимальнодоступимым лотом до STOP OUT");
}
}
else//если же остаток на депозите будет меньше стоп-аута
{
lotCount = currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE));
if(lotCount<MarketInfo(currName,MODE_MINLOT))//если лот меньше минимального лота
{
int pipsProc=(int)round(currMove/(MarketInfo(currName,MODE_MINLOT)*MarketInfo(currName,MODE_TICKVALUE)));
Print(proc,"%-й уровень депозита будет достигнут, з минимальнолопустимым лотом, за ",pipsProc," пп.");
lotCount=MarketInfo(currName,MODE_MINLOT);
}
}
}
else{
//а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах
//как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделает
/*
*/}
//"прическа" для лота
lotCount = MathFloor(lotCount/MarketInfo(currName,MODE_MINLOT))*MarketInfo(currName,MODE_MINLOT);
if(lotCount<MarketInfo(currName,MODE_MINLOT))
{
return MarketInfo(currName,MODE_MINLOT);
}
if(lotCount>MarketInfo(currName,MODE_MAXLOT))
{
return MarketInfo(currName,MODE_MAXLOT);
}
return lotCount;
}
因此lSL是指多少个点到SL
点=0.00001(在5位数的报价上)。
dLotStep = 0.01
公式(LSL*dLotCost*dLotStep))*dLotStep是 错误的
它应该是类似于(LSL*dLotCost*Point))*dLotStep 的东西。
你不需要编造什么。每家经纪公司的手数是不同的,你必须把它调整到合适的大小。积分与此无关
你不需要发明任何东西。每个经纪公司的拍品尺寸都不一样,我们必须把它带到合适的尺寸。分数与此无关。
在我们的案例中,lSL是 以报价点为单位 的缩减规模,而不是以手数为单位的缩减规模。也就是说,积分确实与此有关。
因此,在计算公式中,我们应该乘以(括号中的内容)Point,而不是乘以dLotStep。
另一件事是,这已经是以dLotCost 为代价完成的(连同转换为存款货币)......。
也就是说,我们是第一个在
获得一个整数,然后通过乘以dLotStep ,重新计算回正确的批次单位?
还有一个选项,存款3英镑,可以交易欧元兑美元,把30%放在亏损方......但这是出于一系列的变态行为
就问题而言,lSL是 以报价的点数为单位 的缩水大小,而不是以手数的点数为单位。也就是说,积分与此无关。
因此,在计算公式中,我们应该乘以(括号中的内容)Point,而不是乘以dLotStep。
另一件事是,这已经是以dLotCost 为代价完成的(连同转换为存款货币)......。
也就是说,我们首先在
得到一个整数,然后通过乘以dLotStep 重新计算回正确的批次单位?
是
该公式仍然是错误的(对于iSL>0 的区块)。
TICKVALUE 给出了TICKSIZE 的价格。
而lSL 的单位是POINT 点。
POINT 并不总是与TICKSIZE 相吻合(见Alpari的3位数货币对XAUUSD)。
所以你必须把lSL 从POINT转换为 TICKSIZE。
否则,我们将获得10倍的高估手数(这是我在XAUUSD货币对上观察到的,直到我加入重新计算)。
如果(LSL>0){
lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT将给出一个整数(1或10),我们可以使用int类型的lSL
//这里是它的内容。
PS:对于TC优化的许多通道(>10mln),符号的所有不可改变的参数(TICKSIZE,POINT,TICKVALUE,LOTSTEP,MINLOT,MAXLOT 等)应该被分配给函数init() 中的变量,并在计算中使用这些变量。
包括将TickSize/Point的 值放入一个变量。
该公式仍然是错误的(对于iSL>0 的区块)。
TICKVALUE 给出了TICKSIZE 的价格。
而lSL 的单位是POINT 点。
POINT 并不总是与TICKSIZE 相吻合(见Alpari的3位数货币对XAUUSD)。
所以你必须把lSL 从POINT转换为 TICKSIZE。
否则,我们将获得10倍的高估手数(这是我在XAUUSD货币对上观察到的,直到我加入重新计算)。
如果(LSL>0){
lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT将给出一个整数(1或10),我们可以使用int类型的lSL
//这里是它的内容。
PS:对于优化许多通道(>10mln)的TS,所有不可改变的符号参数(TICKSIZE,POINT,TICKVALUE,LOTSTEP,MINLOT,MAXLOT 等)必须被分配到函数init() 中的变量,并在计算中使用变量。
包括将TickSize/Point的 值放入一个变量。
谢谢你
谢谢
该专题负责人在第一页上发送了他的敬意,然后再也没有回来。
几年前,在某个论坛上讨论过这个问题。我将根据记忆复述,但没有公式。
假设我们交易澳元兑瑞郎货币对。为了解释头寸的利润或亏损是如何形成的,它是相当随意地采取的。在https://www.mql5.com/ru/forum/150912, 也提出了大致相同的话题。
如果我们交易一手100000澳元,那么(按五位数计算)每一个点都能赚取1瑞士法郎(对分母)的利润或损失(这取决于我们走了哪条路,价格走向如何)。
因此,在任何时候,我们都知道我们已经获得/失去了多少瑞士法郎。如果存款货币是美元,收益/损失将被转换为存款货币,使用当时 的美元兑瑞士法郎汇率,如果存款货币是欧元,则使用欧元兑瑞士法郎。以此类推,对于所有货币对和存款货币。
这就是答案:我们不能总是估计准确的正确的地段尺寸。带有请求参数MODE_TICKVALUE的MarketInfo()可以作为一个指导。
因此,答案是:我们不能总是估计准确的正确的地段大小。带有MODE_TICKVALUE请求参数的MarketInfo()可以作为一个指导。
长期以来都是这样核算的。至少在Vinin的 好帖子(TICKSIZE c POINT 不匹配的情况下,手数计算错误)和Martingeil的 旧帖子(手数计算正确,但没有可能设置缩减==0)。
最主要的是TICKVALUE 的正确值应该来自经纪公司(或者在客户上正确计算,如果它是在MT中计算的)。
当这个主题开始时,还没有TICKVALUE 。
而随着它的出现,一切都被简化了,这个话题也被冷落了一阵子。
PS:很快我将发布我的版本--Vinin的版本(它有更简单的公式和iSL==0)和Martingeil的版本(即使是最小手数也能控制资金不足)的混合版本。
特点:1)从AccountFreeMargin()计算余额,而不是从AccountBalance()计算。
2)而且(对于移仓者)考虑到当未平仓的交易在SL上关闭时,余额将减少一定数量。
如果没有足够的钱,即使是最小的余额 - 它将显示手数 -134(错误134 - 没有足够的钱来打开一个交易)。
在这方面,向维宁(和其他有经验的同志)提问:这个代码是自己着色还是你自己做?我试着将片段样式设置为 "代码",但它并没有着色。还是只有在提交帖子后才有颜色?
有一个问题要问Vinin(和其他有经验的同志):代码是自己着色,还是你自己着色?我试着将片段样式设置为 "代码",但它没有颜色。还是只有在提交帖子后才有颜色?
敲定了我的想法(针对有止损百分比的平台)......分享代码......接受建设性的批评
double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000) { double lotCount=0; //1) проверка достаточности средств для проведения торговли if(deposSize < MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT)) { //Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом"); return 0.0; } double currMove=deposSize*proc/100;// расчет процента от величины депозита //расчивываем максимально допустимый лот, до стоп-аута double SOlot = deposSize/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE)+ MarketInfo(currName,MODE_MARGINREQUIRED)*AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100); //расчет величины депозита, при котором сработает стоп-аут double SOval = SOlot*pipsLoss*MarketInfo(currName,MODE_TICKVALUE); ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах { if((deposSize-currMove)<SOval)//проверяем остаток на депозите на превышение значения стоп-аут { if(SOlot<MarketInfo(currName,MODE_MINLOT))//если лот стоп-аута меньше минимального лота { lotCount = MarketInfo(currName,MODE_MINLOT); //находим количесвто пунктов до вылета по стоп-ауту и выбрасываем предупреждение int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE))); Print("При прохождении ценой больше ", pipsSO," пп.- \nторговля будет прекращена по STOP OUT!"); } else//если наш стоп-аут лот больше равно минимального { lotCount = SOlot; int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE))); Print("Достижение STOP OUT, произойдет через ", pipsSO, " и работа будет проведена с максимальнодоступимым лотом до STOP OUT"); } } else//если же остаток на депозите будет меньше стоп-аута { lotCount = currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE)); if(lotCount<MarketInfo(currName,MODE_MINLOT))//если лот меньше минимального лота { int pipsProc=(int)round(currMove/(MarketInfo(currName,MODE_MINLOT)*MarketInfo(currName,MODE_TICKVALUE))); Print(proc,"%-й уровень депозита будет достигнут, з минимальнолопустимым лотом, за ",pipsProc," пп."); lotCount=MarketInfo(currName,MODE_MINLOT); } } } else{ //а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах //как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделает /* */} //"прическа" для лота lotCount = MathFloor(lotCount/MarketInfo(currName,MODE_MINLOT))*MarketInfo(currName,MODE_MINLOT); if(lotCount<MarketInfo(currName,MODE_MINLOT)) { return MarketInfo(currName,MODE_MINLOT); } if(lotCount>MarketInfo(currName,MODE_MAXLOT)) { return MarketInfo(currName,MODE_MAXLOT); } return lotCount; }