#property strict// в самое начало кода вашей программы (если нету там ещё)
// Функцию - за пределы остальных функций программы //+------------------------------------------------------------------+ //| Трейлинг по значению + перенос стопа на уровень безубытка | //+------------------------------------------------------------------+ void TrailingByLevel(string symbol_name, // Имя символа int magic_number, // Magic ордера double level_of_trail, // Уровень, на который ставим стоп (например МА или Parabolic SAR) int trailing_start, // Профит в пунктах для старта трала int trailing_step, // Шаг трала в пунктах int trailing_stop, // Отступ стоплосс от уровня МА или SAR в пунктах int profit_for_breakeven=15, // Профит в пунктах для переноса стопа в безубыток int breakeven_level=5, // Уровень безубытка в пунктах bool use_trail=true, // Флаг использования трала bool use_breakeven=false// Флаг использования безубытка ) { int lv=StopLevel(symbol_name)+1; // Получаем значение Stop Level по символу + 1 пункт (из отдельной функции) for(int i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS)) { if(OrderMagicNumber()!=magic_number) continue; //Если Магик не наш - идем к следующему ордеру if(OrderSymbol()!=symbol_name) continue; //Если Символ не наш - идем к следующему ордеру //--- покупки if(OrderType()==OP_BUY) { int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS); double point=(SymbolInfoDouble(symbol_name,SYMBOL_POINT)); double pb=SymbolInfoDouble(symbol_name,SYMBOL_BID); double profit=pb-OrderOpenPrice(); // Профит позиции в цене (без комиссий и свопов) //--- безубыток if(use_breakeven) { //--- если профит в цене больше заданного if(profit>=profit_for_breakeven*point) { int err=ERR_NO_ERROR; double sl=NormalizeDouble(OrderOpenPrice()+breakeven_level*point,digits); if(pb-lv*point>sl && OrderStopLoss()<sl) { // Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись: // OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ... // ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка //ModifyOrder(-1,sl,-1,err); } if(err==ERR_MARKET_CLOSED) return; } } //--- трал if(use_trail) { //--- если профит в пунктах больше заданного, или изначально задан меньше ноля if(profit>=trailing_start*point || trailing_start==EMPTY) { int err=ERR_NO_ERROR; double sl=NormalizeDouble(level_of_trail-trailing_stop*point,digits); // вычисляем новый уровень стоплосс по значению, переданному в функцию //--- Если новое значение СЛ не ближе Stop Level и если новое положение СЛ больше старого+шаг СЛ, то модифицируем стоп позиции if(pb-lv*point>sl && OrderStopLoss()+trailing_step*point<sl) { // Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись: // OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ... // ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка //ModifyOrder(-1,sl,-1,err); } if(err==ERR_MARKET_CLOSED) return; } } }
//--- Продажи if(OrderType()==OP_SELL) { int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS); double point=(SymbolInfoDouble(symbol_name,SYMBOL_POINT)); double pa=SymbolInfoDouble(symbol_name,SYMBOL_ASK); double profit=OrderOpenPrice()-pa; // Профит позиции в цене (без комиссий и свопов) //--- безубыток if(use_breakeven) { //--- если профит в цене больше заданного if(profit>=profit_for_breakeven*point) { int err=ERR_NO_ERROR; double sl=NormalizeDouble(OrderOpenPrice()-breakeven_level*point,digits); if(pa+lv*point<sl && (OrderStopLoss()>sl || OrderStopLoss()==0)) { // Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись: // OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ... // ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка //ModifyOrder(-1,sl,-1,err); } if(err==ERR_MARKET_CLOSED) break; } } //--- трал if(use_trail) { //--- если профит в пунктах больше заданного, или изначально задан меньше ноля if(profit>=trailing_start*point || trailing_start==EMPTY) { int err=ERR_NO_ERROR; double sl=NormalizeDouble(level_of_trail+trailing_stop*point,digits); // вычисляем новый уровень стоплосс по значению, переданному в функцию //--- Если новое значение СЛ не ближе Stop Level и если новое положение СЛ больше старого+шаг СЛ, то модифицируем стоп позиции if(pa+lv*point<sl && (OrderStopLoss()-trailing_step*point>sl || OrderStopLoss()==0)) { // Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись: // OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ... // ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка //ModifyOrder(-1,sl,-1,err); } if(err==ERR_MARKET_CLOSED) break; } } } } } } //+------------------------------------------------------------------+ int StopLevel(string symbol_name) { int sp=(int)SymbolInfoInteger(symbol_name,SYMBOL_SPREAD); int lv=(int)SymbolInfoInteger(symbol_name,SYMBOL_TRADE_STOPS_LEVEL); return((lv==0)?sp*2:lv); } //+------------------------------------------------------------------+
自分のメモリーチップの話です。:)))
そんな些細なことは、コードを書くときに簡単に再確認し、明確にし、必要に応じて実行し、また忘れるということをしないことです。
よく、トロール機能やブレークイーブン機能を求める人がいることに気づきました。この関数に渡された価格チャート(МАшашкаや放物線など)に線を引く指標の値に応じて、ブレイクイーブンレベルのストップやトレーリングストップ位置を描画する関数をスケッチしてみました。
// Функцию - за пределы остальных функций программы
//+------------------------------------------------------------------+
//| Трейлинг по значению + перенос стопа на уровень безубытка |
//+------------------------------------------------------------------+
void TrailingByLevel(string symbol_name, // Имя символа
int magic_number, // Magic ордера
double level_of_trail, // Уровень, на который ставим стоп (например МА или Parabolic SAR)
int trailing_start, // Профит в пунктах для старта трала
int trailing_step, // Шаг трала в пунктах
int trailing_stop, // Отступ стоплосс от уровня МА или SAR в пунктах
int profit_for_breakeven=15, // Профит в пунктах для переноса стопа в безубыток
int breakeven_level=5, // Уровень безубытка в пунктах
bool use_trail=true, // Флаг использования трала
bool use_breakeven=false // Флаг использования безубытка
)
{
int lv=StopLevel(symbol_name)+1; // Получаем значение Stop Level по символу + 1 пункт (из отдельной функции)
for(int i=OrdersTotal()-1; i>=0; i--) {
if(OrderSelect(i,SELECT_BY_POS)) {
if(OrderMagicNumber()!=magic_number) continue; //Если Магик не наш - идем к следующему ордеру
if(OrderSymbol()!=symbol_name) continue; //Если Символ не наш - идем к следующему ордеру
//--- покупки
if(OrderType()==OP_BUY) {
int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS);
double point=(SymbolInfoDouble(symbol_name,SYMBOL_POINT));
double pb=SymbolInfoDouble(symbol_name,SYMBOL_BID);
double profit=pb-OrderOpenPrice(); // Профит позиции в цене (без комиссий и свопов)
//--- безубыток
if(use_breakeven) {
//--- если профит в цене больше заданного
if(profit>=profit_for_breakeven*point) {
int err=ERR_NO_ERROR;
double sl=NormalizeDouble(OrderOpenPrice()+breakeven_level*point,digits);
if(pb-lv*point>sl && OrderStopLoss()<sl) {
// Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись:
// OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ...
// ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка
//ModifyOrder(-1,sl,-1,err);
}
if(err==ERR_MARKET_CLOSED) return;
}
}
//--- трал
if(use_trail) {
//--- если профит в пунктах больше заданного, или изначально задан меньше ноля
if(profit>=trailing_start*point || trailing_start==EMPTY) {
int err=ERR_NO_ERROR;
double sl=NormalizeDouble(level_of_trail-trailing_stop*point,digits); // вычисляем новый уровень стоплосс по значению, переданному в функцию
//--- Если новое значение СЛ не ближе Stop Level и если новое положение СЛ больше старого+шаг СЛ, то модифицируем стоп позиции
if(pb-lv*point>sl && OrderStopLoss()+trailing_step*point<sl) {
// Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись:
// OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ...
// ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка
//ModifyOrder(-1,sl,-1,err);
}
if(err==ERR_MARKET_CLOSED) return;
}
}
}
//--- Продажи
if(OrderType()==OP_SELL) {
int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS);
double point=(SymbolInfoDouble(symbol_name,SYMBOL_POINT));
double pa=SymbolInfoDouble(symbol_name,SYMBOL_ASK);
double profit=OrderOpenPrice()-pa; // Профит позиции в цене (без комиссий и свопов)
//--- безубыток
if(use_breakeven) {
//--- если профит в цене больше заданного
if(profit>=profit_for_breakeven*point) {
int err=ERR_NO_ERROR;
double sl=NormalizeDouble(OrderOpenPrice()-breakeven_level*point,digits);
if(pa+lv*point<sl && (OrderStopLoss()>sl || OrderStopLoss()==0)) {
// Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись:
// OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ...
// ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка
//ModifyOrder(-1,sl,-1,err);
}
if(err==ERR_MARKET_CLOSED) break;
}
}
//--- трал
if(use_trail) {
//--- если профит в пунктах больше заданного, или изначально задан меньше ноля
if(profit>=trailing_start*point || trailing_start==EMPTY) {
int err=ERR_NO_ERROR;
double sl=NormalizeDouble(level_of_trail+trailing_stop*point,digits); // вычисляем новый уровень стоплосс по значению, переданному в функцию
//--- Если новое значение СЛ не ближе Stop Level и если новое положение СЛ больше старого+шаг СЛ, то модифицируем стоп позиции
if(pa+lv*point<sl && (OrderStopLoss()-trailing_step*point>sl || OrderStopLoss()==0)) {
// Сюда вписываем свою функцию модификации. Можно конечно и стандартной обойтись:
// OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),OrderExpiration(),clrModify); ...
// ... но в ней не предусмотрены проверки кодов возврата торгового сервера и их обработка
//ModifyOrder(-1,sl,-1,err);
}
if(err==ERR_MARKET_CLOSED) break;
}
}
}
}
}
}
//+------------------------------------------------------------------+
int StopLevel(string symbol_name) {
int sp=(int)SymbolInfoInteger(symbol_name,SYMBOL_SPREAD);
int lv=(int)SymbolInfoInteger(symbol_name,SYMBOL_TRADE_STOPS_LEVEL);
return((lv==0)?sp*2:lv);
}
//+------------------------------------------------------------------+
私のEAを改良するのを手伝ってくれませんか?ストップをかけるEAがあるのですが、ストップロスをドラッグする方法がわかりません。全く理解できないので、専門家の力を貸してほしい。
配列の要素の 重さを決定する関数が必要です。ある要素に近い(より近い)他の要素の数が多ければ多いほど、その重みは大きくなる。もしかしたら、すでにそのような機能があるのかもしれません。サンプルに含まれる元素の濃度で重さを決めるようなもの。ありがとうございます。
こんにちは!MQL4テスターで、なぜ1回だけ反復して停止するのかがわかりません?TimeCurrent() が更新されない?アップデートの方法を教えてください。ティック単位ではなく、毎秒、あるいは毎秒5回、EAを動作させたい。
こんにちは!MQL4テスターで、なぜ1回だけ反復して停止するのかが分かりません?TimeCurrent()が更新されない?アップデートの方法を教えてください。多通貨EAはティックで動作するのではなく、毎秒、もしくは毎秒5回動作することが必要です。
このEAはどのように実行するのですか? つまり、エキスパートディレクトリからですか?
start()関数(旧名称、現代版OnTick)は、1ティック ごとに実行されます、つまり、ティックの終了後に実行されるべきものです。そして、それをループさせているのですか?
これはアドバイザーとして、あるいはエキスパートディレクトリから実行しているのですか?
EAのstart()関数(旧名称、現代版OnTick)は1ティック ごとに実行される、つまりティックが終了した時点で終了するはずです。そして、それをループさせているのですか?
https://book.mql4.com/ru/special/index
もちろん、ループさせることも可能です。しかし、次のTICまでには手放すことが望ましい。さもなければ、TICは失われます。必要ですか?
ループさせることは、もちろん可能です。しかし、次のTICまでにはリリースすることが望ましい。さもなければ、TICは失われます。必要なのか?
新しいティック情報は、エンドレスループの中でRefreshRates(); を使って取得することができます。
RefreshRates(); 関数は、チェックするだけ です。データが更新された場合、true を返す。while(!RefreshRates(); - tickを待つ) ということができます。
RefreshRates(); 関数は、 チェックするだけ です。データが更新された場合、true を返す。while(!RefreshRates()); - 刻み目を待つという 方法があります。
リフレッシュ(人を混乱させない)し、更新が成功したか失敗したかのフラグを返します。
SymbolInfoDouble()、SymbolInfoTick()でデータを受信する場合は、なくても大丈夫です。