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は クォートのポイントでの ドローダウンサイズであり、ロットのポイントではありません。つまり、ポイントが関係しているのです。
そのため、計算式では、dLotStepではなく、Pointを(括弧内にあるものを)掛ける必要があります。
もうひとつは、これはすでにdLotCostを 犠牲にして(預金通貨への 変換と一緒に)行われていることですが...。
すなわち、私たちは、最初に
整数を取得し、dLotStepを掛けて ロットの正しい単位に再計算する?
また、EURUSDを取引するための3ポンドの預金とオプションがあり、負け側に30%を置く...しかし、これは一連の変態のうちである。
問題のlSLは 、ロットのポイントではなく、クォートのポイントでの ドローダウンの大きさである。つまり、ポイントは関係ないのです。
したがって、計算式では、dLotStepではなく、Pointを(括弧内にあるものを)掛ける必要があります。
もうひとつは、これはすでにdLotCostを 犠牲にして(預金通貨への変換と一緒に)行われていることですが...。
すなわち、私たちは最初に
整数を取得し、dLotStepを掛けて ロットの正しい単位に再計算する?
はい
計算式がまだ間違っている(iSL> 0のブロックの場合)。
TICKVALUEは 、TICKSIZEの 価格を示す。
そして、lSLは POINT ポイントで示される。
POINTは TICKSIZEと 必ずしも一致しない(Alpariの3桁ペアXAUUSDを 参照)。
そのため、lSLを POINTから TICKSIZEに 変換する必要があります。
さもなければ、10倍の過大評価ロットを得ることになります(これは、再計算を追加するまでXAUUSDペアで私が観察したことです)。
if (lSL>0){。
lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT は整数(1または10)になるので、int型のlSLを使用することができます。
//こんな感じでした。
PS:多くのパス(10mln以上)に最適化されたTCでは、シンボルのすべての変更不可能なパラメータ(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ペアで私が観察したことです)。
if (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の 値を変数に入れることも含む。
ありがとうございました。
感謝
トピックスターは、最初のページで敬意を表して送ったきり、二度と戻ってこない。
数年前、この問題はどこかの掲示板で議論された。記憶をたどりながら、数式を使わずに語り継いでいきます。
例えば、AUDCHFのペアを取引するとします。これは、ポジションの利益や損失がどのように形成されるかを説明するために、極めて恣意的にとられたものである。ほぼ同じ話題が、https://www.mql5.com/ru/forum/150912。
100000AUDを1ロットで取引する場合、(5桁で)1ピップごとに1CHF(ペアの分母)の利益または損失が生じます(それは私たちがどの方向に行き、価格がどの方向に行くかによります)。
したがって、いつでもどれだけのスイスフランを得たり失ったりしたかを知ることができるのです。預入通貨がUSDの場合はUSDCHF、預入通貨がEURの場合はEURCHFと、その 時点の為替レートを用いて、損益を預入通貨に換算しています。例えるなら、すべてのペアと入金通貨についてです。
これが答えです。私たちは、常に正確な正しいロットサイズを見積もることはできません。MarketInfo()でリクエストパラメータ MODE_TICKVALUE を指定すると、目安になります。
したがって、必ずしも正確なロットサイズを見積もることはできない、というのが答えです。MODE_TICKVALUE リクエストパラメータを指定した MarketInfo()が目安になります。
昔からそういう勘定になるんです。少なくともVininの 素敵な投稿(TICKSIZE c POINTが 不一致で間違ったロット計算をする)とMartingeilの 古い投稿(正しいロット計算をするが、ドローダウン==0を設定する可能性がない)では、です。
主な内容は、TICKVALUEの 正しい値が証券会社から届くこと(MTで計算する場合は、クライアントで正しく計算されること)です。
このテーマが始まった当初は、TICKVALUEは 存在しませんでした。
そして、その出現により、すべてが簡素化され、この話題はしばらくお預けとなった。
追記:近々、Vininのバージョン(よりシンプルな式でiSL=0)とMartingeilのバージョン(最小ロットでも資金不足を抑制)のハイブリッドである私のバージョンを投稿する予定です。
特徴:1)AccountBalance()からではなく、AccountFreeMargin()から残高を算出する。
2) また、(シフターの場合)SLでオープントレードがクローズすると、残高が一定量減少することを考慮している。
最低残高でも資金が足りない場合は、ロット数量-134と表示されます(エラー134 - 取引を開くのに十分な資金がありません)。
この点で、Vinin(および他の経験豊富な同志)への質問:このコードは、それ自体で着色されていますか、あなたはそれを自分で行うのですか?スニペットスタイルを「code」にしてみましたが、色がつきませんでした。それとも、投稿後にしか色がつかないのでしょうか?
Vinin(および他の経験豊富な同志)に質問です:コードは自分で着色するのですか、それとも自分で着色するのですか?スニペットスタイルを「code」にしてみたのですが、色がつきません。それとも、投稿後にしか色がつかないのでしょうか?
私のアイデア(ストップ・アウト・パーセンテージのあるプラットフォーム用)を完成させました...コードを共有します...建設的な批判を受け入れます。