2022 lines
No EOL
131 KiB
MQL5
2022 lines
No EOL
131 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| MyFirstIncludeFile.mqh |
|
|
//| dilettantcorner |
|
|
//| dilettantcorner@gmail.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "dilettantcorner"
|
|
#property link "dilettantcorner@gmail.com"
|
|
|
|
#ifndef MY_EXPERT_FUNCTIONS_MQH
|
|
#define MY_EXPERT_FUNCTIONS_MQH
|
|
|
|
namespace std {
|
|
//+------------------------------------------------------------------+
|
|
|
|
ulong Open_Buy_Pos(string symbol,double lot, int slipage, uint magic = NULL, string comment = NULL)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_DEAL;
|
|
reqwest.symbol = symbol;
|
|
reqwest.type = ORDER_TYPE_BUY;
|
|
reqwest.volume = NormalizeDouble(lot,2);
|
|
ENUM_ORDER_TYPE_FILLING fill_type;
|
|
GetFillMode(reqwest.symbol,fill_type);
|
|
::Print("Filling mode: ",fill_type);
|
|
reqwest.type_filling = fill_type;
|
|
|
|
|
|
if(SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_EXEMODE) == SYMBOL_TRADE_EXECUTION_INSTANT ||
|
|
SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_EXEMODE) == SYMBOL_TRADE_EXECUTION_REQUEST)
|
|
{
|
|
double current_ask = SymbolInfoDouble(reqwest.symbol,SYMBOL_ASK);
|
|
reqwest.price = current_ask;
|
|
reqwest.sl = 0;
|
|
reqwest.tp = 0;
|
|
reqwest.deviation = slipage;
|
|
}
|
|
|
|
if(comment != NULL && comment != "") reqwest.comment = comment;
|
|
if(magic > 0) reqwest.magic = magic;
|
|
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Позиция Бай не открыта. Ошибка №",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
ulong deal_ticket = result.deal;
|
|
|
|
if(deal_ticket == 0) break;
|
|
|
|
if(deal_ticket > 0)
|
|
{
|
|
if(HistoryDealSelect(deal_ticket))
|
|
{
|
|
long pos_ticket = HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID);
|
|
|
|
return pos_ticket;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Open_Sell_Pos(string symbol,double lot, int slipage, uint magic = NULL, string comment = NULL)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_DEAL;
|
|
reqwest.symbol = symbol;
|
|
reqwest.type = ORDER_TYPE_SELL;
|
|
reqwest.volume = NormalizeDouble(lot,2);
|
|
ENUM_ORDER_TYPE_FILLING fill_type;
|
|
GetFillMode(reqwest.symbol,fill_type);
|
|
::Print("Filling mode: ",fill_type);
|
|
reqwest.type_filling = fill_type;
|
|
|
|
|
|
if(SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_EXEMODE) == SYMBOL_TRADE_EXECUTION_INSTANT ||
|
|
SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_EXEMODE) == SYMBOL_TRADE_EXECUTION_REQUEST)
|
|
{
|
|
double current_bid = SymbolInfoDouble(reqwest.symbol,SYMBOL_BID);
|
|
reqwest.price = current_bid;
|
|
reqwest.sl = 0;
|
|
reqwest.tp = 0;
|
|
reqwest.deviation = slipage;
|
|
}
|
|
|
|
if(comment != NULL && comment != "") reqwest.comment = comment;
|
|
if(magic > 0) reqwest.magic = magic;
|
|
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Позиция Селл не открыта. Ошибка №",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
ulong deal_ticket = result.deal;
|
|
|
|
if(deal_ticket == 0) break;
|
|
|
|
if(deal_ticket > 0)
|
|
{
|
|
if(HistoryDealSelect(deal_ticket))
|
|
{
|
|
long pos_ticket = HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID);
|
|
|
|
return pos_ticket;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Set_Buy_Order(string symbol,
|
|
double lot,
|
|
double open_price,
|
|
int stop_loss,
|
|
int take_profit,
|
|
uint magic = NULL,
|
|
datetime expiration_time = 0,
|
|
string comment = NULL)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_PENDING;
|
|
reqwest.symbol = symbol;
|
|
reqwest.volume = NormalizeDouble(lot,2);
|
|
reqwest.type_filling = ORDER_FILLING_RETURN;
|
|
|
|
int digits = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_DIGITS);
|
|
reqwest.price = NormalizeDouble(open_price,digits);
|
|
double current_ask = SymbolInfoDouble(reqwest.symbol,SYMBOL_ASK);
|
|
if(reqwest.price > current_ask) reqwest.type = ORDER_TYPE_BUY_STOP;
|
|
else reqwest.type = ORDER_TYPE_BUY_LIMIT;
|
|
|
|
int stop_level = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
double point = SymbolInfoDouble(reqwest.symbol,SYMBOL_POINT);
|
|
if(stop_loss > 0)
|
|
{
|
|
if(stop_loss < stop_level) stop_loss = stop_level;
|
|
reqwest.sl = NormalizeDouble(reqwest.price - stop_loss * point,digits);
|
|
}
|
|
else reqwest.sl = 0;
|
|
|
|
if(take_profit > 0)
|
|
{
|
|
if(take_profit < stop_level) take_profit = stop_level;
|
|
reqwest.tp = NormalizeDouble(reqwest.price + take_profit * point,digits);
|
|
}
|
|
else reqwest.tp = 0;
|
|
|
|
if(expiration_time == 0)
|
|
{
|
|
int symb_exp = (int)SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_MODE);
|
|
if((SYMBOL_EXPIRATION_GTC & symb_exp) != SYMBOL_EXPIRATION_GTC) reqwest.type_time = ORDER_TIME_DAY;
|
|
else reqwest.type_time = ORDER_TIME_GTC;
|
|
}
|
|
|
|
if(comment != NULL && comment != "") reqwest.comment = comment;
|
|
if(magic > 0) reqwest.magic = magic;
|
|
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Отложенный ордер Бай не установлен. Ошибка №",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
ulong order_ticket = result.order;
|
|
|
|
if(order_ticket > 0) return order_ticket;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Set_Sell_Order(string symbol,
|
|
double lot,
|
|
double open_price,
|
|
int stop_loss,
|
|
int take_profit,
|
|
uint magic = NULL,
|
|
datetime expiration_time = 0,
|
|
string comment = NULL)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_PENDING;
|
|
reqwest.symbol = symbol;
|
|
reqwest.volume = NormalizeDouble(lot,2);
|
|
reqwest.type_filling = ORDER_FILLING_RETURN;
|
|
|
|
int digits = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_DIGITS);
|
|
reqwest.price = NormalizeDouble(open_price,digits);
|
|
double current_bid = SymbolInfoDouble(reqwest.symbol,SYMBOL_BID);
|
|
if(reqwest.price < current_bid) reqwest.type = ORDER_TYPE_SELL_STOP;
|
|
else reqwest.type = ORDER_TYPE_SELL_LIMIT;
|
|
|
|
int stop_level = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
double point = SymbolInfoDouble(reqwest.symbol,SYMBOL_POINT);
|
|
if(stop_loss > 0)
|
|
{
|
|
if(stop_loss < stop_level) stop_loss = stop_level;
|
|
reqwest.sl = NormalizeDouble(reqwest.price + stop_loss * point,digits);
|
|
}
|
|
else reqwest.sl = 0;
|
|
|
|
if(take_profit > 0)
|
|
{
|
|
if(take_profit < stop_level) take_profit = stop_level;
|
|
reqwest.tp = NormalizeDouble(reqwest.price - take_profit * point,digits);
|
|
}
|
|
else reqwest.tp = 0;
|
|
|
|
if(expiration_time == 0)
|
|
{
|
|
int symb_exp = (int)SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_MODE);
|
|
if((SYMBOL_EXPIRATION_GTC & symb_exp) != SYMBOL_EXPIRATION_GTC) reqwest.type_time = ORDER_TIME_DAY;
|
|
else reqwest.type_time = ORDER_TIME_GTC;
|
|
}
|
|
|
|
if(comment != NULL && comment != "") reqwest.comment = comment;
|
|
if(magic > 0) reqwest.magic = magic;
|
|
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Отложенный ордер Селл не установлен. Ошибка №",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
ulong order_ticket = result.order;
|
|
|
|
if(order_ticket > 0) return order_ticket;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Set_Buy_Order(string symbol,
|
|
double lot,
|
|
double open_price,
|
|
double stop_loss,
|
|
double take_profit,
|
|
uint magic = NULL,
|
|
datetime expiration_time = 0,
|
|
string comment = NULL)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_PENDING;
|
|
reqwest.symbol = symbol;
|
|
reqwest.volume = NormalizeDouble(lot,2);
|
|
reqwest.type_filling = ORDER_FILLING_RETURN;
|
|
|
|
int digits = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_DIGITS);
|
|
reqwest.price = NormalizeDouble(open_price,digits);
|
|
double current_ask = SymbolInfoDouble(reqwest.symbol,SYMBOL_ASK);
|
|
if(reqwest.price > current_ask) reqwest.type = ORDER_TYPE_BUY_STOP;
|
|
else reqwest.type = ORDER_TYPE_BUY_LIMIT;
|
|
|
|
int stop_level = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
double point = SymbolInfoDouble(reqwest.symbol,SYMBOL_POINT);
|
|
if(stop_loss > 0)
|
|
{
|
|
double stop_dist = DistPrices(reqwest.price,stop_loss,symbol);
|
|
if(stop_dist < stop_level) stop_loss = reqwest.price - stop_level * point;
|
|
reqwest.sl = NormalizeDouble(stop_loss,digits);
|
|
}
|
|
else reqwest.sl = 0;
|
|
|
|
if(take_profit > 0)
|
|
{
|
|
double stop_dist = DistPrices(reqwest.price,take_profit,symbol);
|
|
if(stop_dist < stop_level) take_profit = reqwest.price + stop_level * point;
|
|
reqwest.tp = NormalizeDouble(take_profit,digits);
|
|
}
|
|
else reqwest.tp = 0;
|
|
|
|
if(expiration_time == 0)
|
|
{
|
|
int symb_exp = (int)SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_MODE);
|
|
if((SYMBOL_EXPIRATION_GTC & symb_exp) != SYMBOL_EXPIRATION_GTC) reqwest.type_time = ORDER_TIME_DAY;
|
|
else reqwest.type_time = ORDER_TIME_GTC;
|
|
}
|
|
|
|
if(comment != NULL && comment != "") reqwest.comment = comment;
|
|
if(magic > 0) reqwest.magic = magic;
|
|
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Отложенный ордер Бай не установлен. Ошибка №",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
ulong order_ticket = result.order;
|
|
|
|
if(order_ticket > 0) return order_ticket;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Set_Sell_Order(string symbol,
|
|
double lot,
|
|
double open_price,
|
|
double stop_loss,
|
|
double take_profit,
|
|
uint magic = NULL,
|
|
datetime expiration_time = 0,
|
|
string comment = NULL)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_PENDING;
|
|
reqwest.symbol = symbol;
|
|
reqwest.volume = NormalizeDouble(lot,2);
|
|
reqwest.type_filling = ORDER_FILLING_RETURN;
|
|
|
|
int digits = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_DIGITS);
|
|
reqwest.price = NormalizeDouble(open_price,digits);
|
|
double current_bid = SymbolInfoDouble(reqwest.symbol,SYMBOL_BID);
|
|
if(reqwest.price < current_bid) reqwest.type = ORDER_TYPE_SELL_STOP;
|
|
else reqwest.type = ORDER_TYPE_SELL_LIMIT;
|
|
|
|
int stop_level = (int)SymbolInfoInteger(reqwest.symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
double point = SymbolInfoDouble(reqwest.symbol,SYMBOL_POINT);
|
|
if(stop_loss > 0)
|
|
{
|
|
double stop_dist = DistPrices(reqwest.price,stop_loss,symbol);
|
|
if(stop_dist < stop_level) stop_loss = reqwest.price + stop_level * point;
|
|
reqwest.sl = NormalizeDouble(stop_loss,digits);
|
|
}
|
|
else reqwest.sl = 0;
|
|
|
|
if(take_profit > 0)
|
|
{
|
|
double stop_dist = DistPrices(reqwest.price,take_profit,symbol);
|
|
if(take_profit < stop_level) take_profit = reqwest.price + stop_level * point;
|
|
reqwest.tp = NormalizeDouble(take_profit,digits);
|
|
}
|
|
else reqwest.tp = 0;
|
|
|
|
if(expiration_time == 0)
|
|
{
|
|
int symb_exp = (int)SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_MODE);
|
|
if((SYMBOL_EXPIRATION_GTC & symb_exp) != SYMBOL_EXPIRATION_GTC) reqwest.type_time = ORDER_TIME_DAY;
|
|
else reqwest.type_time = ORDER_TIME_GTC;
|
|
}
|
|
|
|
if(comment != NULL && comment != "") reqwest.comment = comment;
|
|
if(magic > 0) reqwest.magic = magic;
|
|
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Отложенный ордер Селл не установлен. Ошибка №",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
ulong order_ticket = result.order;
|
|
|
|
if(order_ticket > 0) return order_ticket;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
bool Position_SLTP(ulong position,double SL,double TP)
|
|
{
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
double pos_op = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
string pos_symb = PositionGetString(POSITION_SYMBOL);
|
|
ulong pos_mag = PositionGetInteger(POSITION_MAGIC);
|
|
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
int symb_digits = (int)SymbolInfoInteger(pos_symb,SYMBOL_DIGITS);
|
|
double symb_point = SymbolInfoDouble(pos_symb,SYMBOL_POINT);
|
|
int freez_level = (int)SymbolInfoInteger(pos_symb,SYMBOL_TRADE_FREEZE_LEVEL);
|
|
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
if(pos_type == POSITION_TYPE_BUY)
|
|
{
|
|
double current_bid = SymbolInfoDouble(pos_symb,SYMBOL_BID);
|
|
if(SL < 0) reqwest.sl = 0;
|
|
else if(SL > 0)
|
|
{
|
|
reqwest.sl = NormalizeDouble(SL,symb_digits);
|
|
if(MathAbs(current_bid - reqwest.sl) / symb_point < freez_level)
|
|
reqwest.sl = NormalizeDouble(current_bid + freez_level * symb_point,symb_digits);
|
|
}
|
|
|
|
if(TP < 0) reqwest.tp = 0;
|
|
else if(TP > 0)
|
|
{
|
|
reqwest.tp = NormalizeDouble(TP,symb_digits);
|
|
if(MathAbs(current_bid - reqwest.tp) / symb_point < freez_level)
|
|
reqwest.tp = NormalizeDouble(current_bid + freez_level * symb_point,symb_digits);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(SL < 0) reqwest.sl = 0;
|
|
else if(SL > 0)
|
|
{
|
|
reqwest.sl = NormalizeDouble(SL,symb_digits);
|
|
double current_ask = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
if(MathAbs(current_ask - reqwest.sl) / symb_point < freez_level)
|
|
reqwest.sl = NormalizeDouble(current_ask + freez_level * symb_point,symb_digits);
|
|
}
|
|
|
|
if(TP < 0) reqwest.tp = 0;
|
|
else if(TP > 0)
|
|
{
|
|
reqwest.tp = NormalizeDouble(TP,symb_digits);
|
|
double current_ask = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
if(MathAbs(current_ask - reqwest.tp) / symb_point < freez_level)
|
|
reqwest.tp = NormalizeDouble(current_ask - freez_level * symb_point,symb_digits);
|
|
}
|
|
}
|
|
reqwest.position = position;
|
|
reqwest.magic = pos_mag;
|
|
reqwest.symbol = pos_symb;
|
|
reqwest.action = TRADE_ACTION_SLTP;
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Позиция №",position," не была модифицирована. Ошибка№",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
else Print("Позиция №",position," не найдена.");
|
|
|
|
return false;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
bool Position_SLTP(ulong position,int SL,int TP)
|
|
{
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
double pos_op = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
string pos_symb = PositionGetString(POSITION_SYMBOL);
|
|
ulong pos_mag = PositionGetInteger(POSITION_MAGIC);
|
|
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
int symb_digits = (int)SymbolInfoInteger(pos_symb,SYMBOL_DIGITS);
|
|
double symb_point = SymbolInfoDouble(pos_symb,SYMBOL_POINT);
|
|
int freez_level = (int)SymbolInfoInteger(pos_symb,SYMBOL_TRADE_FREEZE_LEVEL);
|
|
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
if(pos_type == POSITION_TYPE_BUY)
|
|
{
|
|
if(SL < 0) reqwest.sl = 0;
|
|
else if(SL > 0)
|
|
{
|
|
if(SL < freez_level) SL = freez_level;
|
|
reqwest.sl = NormalizeDouble(pos_op - SL * symb_point,symb_digits);
|
|
double current_bid = SymbolInfoDouble(pos_symb,SYMBOL_BID);
|
|
if(MathAbs(current_bid - reqwest.sl) / symb_point < freez_level)
|
|
reqwest.sl = NormalizeDouble(current_bid - SL * symb_point,symb_digits);
|
|
}
|
|
|
|
if(TP < 0) reqwest.tp = 0;
|
|
else if(TP > 0)
|
|
{
|
|
if(TP < freez_level) TP = freez_level;
|
|
reqwest.tp = NormalizeDouble(pos_op + TP * symb_point,symb_digits);
|
|
double current_bid = SymbolInfoDouble(pos_symb,SYMBOL_BID);
|
|
if(MathAbs(current_bid - reqwest.tp) / symb_point < freez_level)
|
|
reqwest.tp = NormalizeDouble(current_bid + TP * symb_point,symb_digits);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(SL < 0) reqwest.sl = 0;
|
|
else if(SL > 0)
|
|
{
|
|
if(SL < freez_level) SL = freez_level;
|
|
reqwest.sl = NormalizeDouble(pos_op + SL * symb_point,symb_digits);
|
|
double current_ask = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
if(MathAbs(current_ask - reqwest.sl) / symb_point < freez_level)
|
|
reqwest.sl = NormalizeDouble(current_ask + SL * symb_point,symb_digits);
|
|
}
|
|
|
|
if(TP < 0) reqwest.tp = 0;
|
|
else if(TP > 0)
|
|
{
|
|
if(TP < freez_level) TP = freez_level;
|
|
reqwest.tp = NormalizeDouble(pos_op - TP * symb_point,symb_digits);
|
|
double current_ask = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
if(MathAbs(current_ask - reqwest.tp) / symb_point < freez_level)
|
|
reqwest.tp = NormalizeDouble(current_ask - TP * symb_point,symb_digits);
|
|
}
|
|
}
|
|
reqwest.position = position;
|
|
reqwest.magic = pos_mag;
|
|
reqwest.symbol = pos_symb;
|
|
reqwest.action = TRADE_ACTION_SLTP;
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Позиция №",position," не была модифицирована. Ошибка№",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
else Print("Позиция №",position," не найдена.");
|
|
|
|
return false;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
int CountPositions(ulong magic , string symbol)
|
|
{
|
|
int count = 0;
|
|
|
|
for(int i = 0;i < PositionsTotal();i++)
|
|
{
|
|
ulong pos = PositionGetTicket(i);
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
ulong pos_mag = PositionGetInteger(POSITION_MAGIC);
|
|
string pos_symb = PositionGetString(POSITION_SYMBOL);
|
|
|
|
if(pos_mag == magic && pos_symb == symbol) count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
int CountPositions(const MqlParam &Params[])
|
|
{
|
|
uint magic = NULL;
|
|
string symbol = "";
|
|
ENUM_POSITION_TYPE type = -1;
|
|
int param_size = ArraySize(Params);
|
|
|
|
for(int i = 0;i < param_size;i++)
|
|
{
|
|
if(Params[i].type == TYPE_UINT) magic = (uint)Params[i].integer_value;
|
|
if(Params[i].type == TYPE_STRING) symbol = Params[i].string_value;
|
|
if(Params[i].type == TYPE_INT) type = (ENUM_POSITION_TYPE)Params[i].integer_value;
|
|
}
|
|
|
|
int count = 0;
|
|
|
|
long total_pos = PositionsTotal();
|
|
for(int i = 0;i < total_pos;i++)
|
|
{
|
|
ulong position = PositionGetTicket(i);
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
uint pos_magic = (uint)PositionGetInteger(POSITION_MAGIC);
|
|
string pos_symbol = PositionGetString(POSITION_SYMBOL);
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
if((symbol == "" || symbol == pos_symbol) && (magic == NULL || magic == pos_magic) && (type == -1 || type == pos_type)) count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
int GetPositionsTickets(const MqlParam &Params[] , ulong &Positions[])
|
|
{
|
|
::ArrayFree(Positions);
|
|
|
|
int size = CountPositions(Params);
|
|
|
|
ArrayResize(Positions,size);
|
|
|
|
uint magic = NULL;
|
|
string symbol = "";
|
|
ENUM_POSITION_TYPE type = -1;
|
|
int param_size = ArraySize(Params);
|
|
|
|
for(int i = 0;i < param_size;i++)
|
|
{
|
|
if(Params[i].type == TYPE_UINT) magic = (uint)Params[i].integer_value;
|
|
if(Params[i].type == TYPE_STRING) symbol = Params[i].string_value;
|
|
if(Params[i].type == TYPE_INT) type = (ENUM_POSITION_TYPE)Params[i].integer_value;
|
|
}
|
|
|
|
long total_pos = PositionsTotal();
|
|
int index = 0;
|
|
for(int i = 0;i < total_pos;i++)
|
|
{
|
|
ulong position = PositionGetTicket(i);
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
uint pos_magic = (uint)PositionGetInteger(POSITION_MAGIC);
|
|
string pos_symbol = PositionGetString(POSITION_SYMBOL);
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
if((symbol == "" || symbol == pos_symbol) && (magic == NULL || magic == pos_magic) && (type == -1 || type == pos_type))
|
|
{
|
|
Positions[index] = position;
|
|
index++;
|
|
if(index >= size) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
int CountPositions(const MqlParam &Params[],const double level_1,const double level_2,const string ctrl_symbol)
|
|
{
|
|
double point = SymbolInfoDouble(ctrl_symbol,SYMBOL_POINT);
|
|
if(level_1 / point == level_2 / point)
|
|
{
|
|
Print("Не верно заданы уровни");
|
|
return 0;
|
|
}
|
|
double upLevel = MathMax(level_1,level_2);
|
|
double dnLevel;
|
|
if(upLevel == level_1) dnLevel = level_2;
|
|
else dnLevel = level_1;
|
|
|
|
uint magic = NULL;
|
|
string symbol = "";
|
|
ENUM_POSITION_TYPE type = -1;
|
|
int param_size = ArraySize(Params);
|
|
|
|
for(int i = 0;i < param_size;i++)
|
|
{
|
|
if(Params[i].type == TYPE_UINT) magic = (uint)Params[i].integer_value;
|
|
if(Params[i].type == TYPE_STRING)
|
|
{
|
|
if(ctrl_symbol != Params[i].string_value)
|
|
{
|
|
Print("Ошибка указания символа");
|
|
return 0;
|
|
}
|
|
symbol = Params[i].string_value;
|
|
}
|
|
if(Params[i].type == TYPE_INT) type = (ENUM_POSITION_TYPE)Params[i].integer_value;
|
|
}
|
|
|
|
int count = 0;
|
|
|
|
long total_pos = PositionsTotal();
|
|
for(int i = 0;i < total_pos;i++)
|
|
{
|
|
ulong position = PositionGetTicket(i);
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
uint pos_magic = (uint)PositionGetInteger(POSITION_MAGIC);
|
|
string pos_symbol = PositionGetString(POSITION_SYMBOL);
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
if((symbol == "" || symbol == pos_symbol) && (magic == NULL || magic == pos_magic) && (type == -1 || type == pos_type))
|
|
{
|
|
double op = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
if(op / point > dnLevel / point && op / point < upLevel / point) count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
int CountOrders(const MqlParam &Params[],const double level_1,const double level_2,const string ctrl_symbol)
|
|
{
|
|
double point = SymbolInfoDouble(ctrl_symbol,SYMBOL_POINT);
|
|
if(level_1 / point == level_2 / point)
|
|
{
|
|
Print("Не верно заданы уровни");
|
|
return 0;
|
|
}
|
|
double upLevel = MathMax(level_1,level_2);
|
|
double dnLevel;
|
|
if(upLevel == level_1) dnLevel = level_2;
|
|
else dnLevel = level_1;
|
|
|
|
uint magic = NULL;
|
|
string symbol = "";
|
|
ENUM_ORDER_TYPE type = -1;
|
|
int param_size = ArraySize(Params);
|
|
|
|
for(int i = 0;i < param_size;i++)
|
|
{
|
|
if(Params[i].type == TYPE_UINT) magic = (uint)Params[i].integer_value;
|
|
if(Params[i].type == TYPE_STRING)
|
|
{
|
|
if(ctrl_symbol != Params[i].string_value)
|
|
{
|
|
Print("Ошибка указания символа");
|
|
return 0;
|
|
}
|
|
symbol = Params[i].string_value;
|
|
}
|
|
if(Params[i].type == TYPE_INT) type = (ENUM_ORDER_TYPE)Params[i].integer_value;
|
|
}
|
|
|
|
int count = 0;
|
|
|
|
long total_ord = OrdersTotal();
|
|
if(total_ord == 0) return 0;
|
|
for(int i = 0;i < total_ord;i++)
|
|
{
|
|
ulong order = OrderGetTicket(i);
|
|
if(OrderSelect(order))
|
|
{
|
|
uint ord_magic = (uint)OrderGetInteger(ORDER_MAGIC);
|
|
string ord_symbol = OrderGetString(ORDER_SYMBOL);
|
|
ENUM_ORDER_TYPE ord_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
|
|
|
if((symbol == "" || symbol == ord_symbol) && (magic == NULL || magic == ord_magic) && (type == -1 || type == ord_type))
|
|
{
|
|
double op = OrderGetDouble(ORDER_PRICE_OPEN);
|
|
if(op / point > dnLevel / point && op / point < upLevel / point) count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
int DistPrices(double priceA , double priceB , string symbol = NULL)
|
|
{
|
|
return (int)(MathAbs(priceA - priceB) / SymbolInfoDouble(symbol,SYMBOL_POINT));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
double LotSize(string symbol, ENUM_ORDER_TYPE type, double entry, double exit, double Foundation, double risk)
|
|
{
|
|
double lotMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
|
|
double lotMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
|
|
double lotStep = SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
|
|
|
|
double lot = lotMin;
|
|
|
|
double currencyRisk = (Foundation / 100) * risk;
|
|
currencyRisk = floor(currencyRisk * 100) / 100;
|
|
Print("Risk in money = ",currencyRisk);
|
|
|
|
double profit = 0;
|
|
|
|
if(OrderCalcProfit(type,symbol,lot,entry,exit,profit))
|
|
{
|
|
if(MathAbs(profit) <= currencyRisk)
|
|
{
|
|
profit = MathAbs(profit);
|
|
lot = (currencyRisk / profit) * lotMin;
|
|
lot = floor(lot / lotStep) * lotStep;
|
|
if(lot > lotMax) lot = lotMax;
|
|
}
|
|
else
|
|
{
|
|
Print("Риски превышают максимально доступное значение");
|
|
return lotMin;
|
|
}
|
|
}
|
|
|
|
for(double i = lot;i >= lotMin;i -= lotStep)
|
|
{
|
|
if(OrderCalcProfit(type,symbol,lot,entry,exit,profit))
|
|
{
|
|
if(MathAbs(profit) <= currencyRisk)
|
|
{
|
|
lot = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NormalizeDouble(lot,2);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
double QoutNormalize(double value, string symbol)
|
|
{
|
|
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
|
|
double tick_size = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
|
|
int digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
|
|
|
|
int iValue = (int)(value / point);
|
|
int step = (int)(tick_size / point);
|
|
|
|
int max_step;
|
|
if(step < 10) max_step = 10;
|
|
else if(step >= 10 && step < 100) max_step = 100;
|
|
else if(step >= 100 && step < 1000) max_step = 1000;
|
|
else if(step >= 1000 && step < 10000) max_step = 10000;
|
|
else max_step = 100000;
|
|
|
|
int lost_value = iValue % max_step;
|
|
|
|
if(lost_value % step == 0)
|
|
{
|
|
return (NormalizeDouble(iValue * point,digits));
|
|
}
|
|
|
|
iValue /= max_step;
|
|
for(int i = step;i < max_step;i += step)
|
|
{
|
|
if(lost_value < i)
|
|
{
|
|
lost_value = i;
|
|
break;
|
|
}
|
|
else if(i + step >= max_step)
|
|
{
|
|
iValue++;
|
|
lost_value = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
iValue = iValue * max_step + lost_value;
|
|
value = iValue * point;
|
|
|
|
return NormalizeDouble(value,digits);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
double LotNormalize(double volume, string symbol)
|
|
{
|
|
double lotMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
|
|
double lotMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
|
|
double lotStep = SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
|
|
|
|
if(volume < lotMin) return NormalizeDouble(lotMin,2);
|
|
else if(volume > lotMax) return NormalizeDouble(lotMax,2);
|
|
else
|
|
{
|
|
int i_volume = (int)(volume / lotStep);
|
|
volume = i_volume * lotStep;
|
|
}
|
|
|
|
return NormalizeDouble(volume,2);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
int CountOrders(const MqlParam &Params[])
|
|
{
|
|
uint magic = NULL;
|
|
string symbol = "";
|
|
ENUM_ORDER_TYPE type = -1;
|
|
int param_size = ArraySize(Params);
|
|
|
|
for(int i = 0;i < param_size;i++)
|
|
{
|
|
if(Params[i].type == TYPE_UINT) magic = (uint)Params[i].integer_value;
|
|
if(Params[i].type == TYPE_STRING) symbol = Params[i].string_value;
|
|
if(Params[i].type == TYPE_INT) type = (ENUM_ORDER_TYPE)Params[i].integer_value;
|
|
}
|
|
|
|
int count = 0;
|
|
|
|
long total_ord = OrdersTotal();
|
|
if(total_ord == 0) return 0;
|
|
for(int i = 0;i < total_ord;i++)
|
|
{
|
|
ulong order = OrderGetTicket(i);
|
|
//Print("cur order = ",order);
|
|
if(OrderSelect(order))
|
|
{
|
|
uint ord_magic = (uint)OrderGetInteger(ORDER_MAGIC);
|
|
string ord_symbol = OrderGetString(ORDER_SYMBOL);
|
|
ENUM_ORDER_TYPE ord_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
|
|
|
if((symbol == "" || symbol == ord_symbol) && (magic == NULL || magic == ord_magic) && (type == -1 || type == ord_type)) count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
int GetPendingTickets(const MqlParam &Params[] , ulong &Orders[])
|
|
{
|
|
int size = CountOrders(Params);
|
|
ArrayResize(Orders,size);
|
|
|
|
uint magic = NULL;
|
|
string symbol = "";
|
|
ENUM_ORDER_TYPE type = -1;
|
|
int param_size = ArraySize(Params);
|
|
|
|
for(int i = 0;i < param_size;i++)
|
|
{
|
|
if(Params[i].type == TYPE_UINT) magic = (uint)Params[i].integer_value;
|
|
if(Params[i].type == TYPE_STRING) symbol = Params[i].string_value;
|
|
if(Params[i].type == TYPE_INT) type = (ENUM_ORDER_TYPE)Params[i].integer_value;
|
|
}
|
|
|
|
long total_ord = OrdersTotal();
|
|
int index = 0;
|
|
for(int i = 0;i < total_ord;i++)
|
|
{
|
|
ulong order = OrderGetTicket(i);
|
|
if(OrderSelect(order))
|
|
{
|
|
uint ord_magic = (uint)OrderGetInteger(ORDER_MAGIC);
|
|
string ord_symbol = OrderGetString(ORDER_SYMBOL);
|
|
ENUM_ORDER_TYPE ord_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
|
|
|
if((symbol == "" || symbol == ord_symbol) && (magic == NULL || magic == ord_magic) && (type == -1 || type == ord_type))
|
|
{
|
|
Orders[index] = order;
|
|
index++;
|
|
if(index >= size) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
int GetHandle(string symbol, ENUM_TIMEFRAMES tf, ENUM_INDICATOR ind, const MqlParam &Params[])
|
|
{
|
|
if(ind == IND_CUSTOM && Params[0].type != TYPE_STRING)
|
|
{
|
|
Print("Отсутствует имя пользовательского индикатора.");
|
|
return INVALID_HANDLE;
|
|
}
|
|
return IndicatorCreate(symbol,tf,ind,ArraySize(Params),Params);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
bool Order_Modify(ulong order,double entry,int SL,int TP)
|
|
{
|
|
if(OrderSelect(order))
|
|
{
|
|
double ord_op = OrderGetDouble(ORDER_PRICE_OPEN);
|
|
string ord_symb = OrderGetString(ORDER_SYMBOL);
|
|
ulong ord_mag = OrderGetInteger(ORDER_MAGIC);
|
|
|
|
ENUM_ORDER_TYPE ord_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
|
|
|
int symb_digits = (int)SymbolInfoInteger(ord_symb,SYMBOL_DIGITS);
|
|
double symb_point = SymbolInfoDouble(ord_symb,SYMBOL_POINT);
|
|
int stop_level = (int)SymbolInfoInteger(ord_symb,SYMBOL_TRADE_STOPS_LEVEL);
|
|
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
if(ord_type == ORDER_TYPE_BUY_STOP || ord_type == ORDER_TYPE_BUY_LIMIT)
|
|
{
|
|
if(entry > 0) reqwest.price = NormalizeDouble(entry,symb_digits);
|
|
else reqwest.price = NormalizeDouble(ord_op,symb_digits);
|
|
|
|
double current_ask = SymbolInfoDouble(ord_symb,SYMBOL_ASK);
|
|
if(reqwest.price <= current_ask) reqwest.type = ORDER_TYPE_BUY_LIMIT;
|
|
else reqwest.type = ORDER_TYPE_BUY_STOP;
|
|
|
|
if(SL < 0) reqwest.sl = 0;
|
|
else if(SL > 0)
|
|
{
|
|
if(SL < stop_level) SL = stop_level;
|
|
reqwest.sl = NormalizeDouble(reqwest.price - SL * symb_point,symb_digits);
|
|
//double current_bid = SymbolInfoDouble(pos_symb,SYMBOL_BID);
|
|
//if(MathAbs(current_bid - reqwest.sl) / symb_point < freez_level)
|
|
// reqwest.sl = NormalizeDouble(current_bid - SL * symb_point,symb_digits);
|
|
}
|
|
|
|
if(TP < 0) reqwest.tp = 0;
|
|
else if(TP > 0)
|
|
{
|
|
if(TP < stop_level) TP = stop_level;
|
|
reqwest.tp = NormalizeDouble(reqwest.price + TP * symb_point,symb_digits);
|
|
//double current_bid = SymbolInfoDouble(pos_symb,SYMBOL_BID);
|
|
//if(MathAbs(current_bid - reqwest.tp) / symb_point < freez_level)
|
|
// reqwest.tp = NormalizeDouble(current_bid + TP * symb_point,symb_digits);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(entry > 0) reqwest.price = NormalizeDouble(entry,symb_digits);
|
|
else reqwest.price = NormalizeDouble(ord_op,symb_digits);
|
|
|
|
double current_bid = SymbolInfoDouble(ord_symb,SYMBOL_BID);
|
|
if(reqwest.price >= current_bid) reqwest.type = ORDER_TYPE_SELL_LIMIT;
|
|
else reqwest.type = ORDER_TYPE_SELL_STOP;
|
|
|
|
|
|
if(SL < 0) reqwest.sl = 0;
|
|
else if(SL > 0)
|
|
{
|
|
if(SL < stop_level) SL = stop_level;
|
|
reqwest.sl = NormalizeDouble(reqwest.price + SL * symb_point,symb_digits);
|
|
//double current_ask = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
//if(MathAbs(current_ask - reqwest.sl) / symb_point < freez_level)
|
|
// reqwest.sl = NormalizeDouble(current_ask + SL * symb_point,symb_digits);
|
|
}
|
|
|
|
if(TP < 0) reqwest.tp = 0;
|
|
else if(TP > 0)
|
|
{
|
|
if(TP < stop_level) TP = stop_level;
|
|
reqwest.tp = NormalizeDouble(reqwest.price - TP * symb_point,symb_digits);
|
|
//double current_ask = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
//if(MathAbs(current_ask - reqwest.tp) / symb_point < freez_level)
|
|
// reqwest.tp = NormalizeDouble(current_ask - TP * symb_point,symb_digits);
|
|
}
|
|
}
|
|
reqwest.order = order;
|
|
reqwest.magic = ord_mag;
|
|
reqwest.symbol = ord_symb;
|
|
reqwest.action = TRADE_ACTION_MODIFY;
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Ордер №",order," не был модифицирован. Ошибка№",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
else Print("Ордер №",order," не найден.");
|
|
|
|
return false;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
bool Delete_Order(ulong order)
|
|
{
|
|
if(OrderSelect(order))
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_REMOVE;
|
|
reqwest.order = order;
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Ордер №",order," не был удален. Ошибка№",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
else Print("Ордер №",order," не онаружен.");
|
|
|
|
return false;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
enum LAST_POSITION_OPTION
|
|
{
|
|
LAST_POSITION_UP,
|
|
LAST_POSITION_DOWN,
|
|
LAST_POSITION_TIME
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
ulong Ticket_Last_Buy(const ulong &Positions[] , LAST_POSITION_OPTION last_pos)
|
|
{
|
|
ulong ticket = 0;
|
|
double open = 0;
|
|
datetime time = 0;
|
|
|
|
int size = ArraySize(Positions);
|
|
for(int i = 0;i < size;i++)
|
|
{
|
|
ulong pos = Positions[i];
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
datetime pos_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
|
|
if(last_pos == LAST_POSITION_DOWN)
|
|
{
|
|
if(open == 0 || pos_open < open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_UP)
|
|
{
|
|
if(open == 0 || pos_open > open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_TIME)
|
|
{
|
|
if(time == 0 || pos_time > time)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ticket;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Ticket_Last_Sell(const ulong &Positions[] , LAST_POSITION_OPTION last_pos)
|
|
{
|
|
ulong ticket = 0;
|
|
double open = 0;
|
|
datetime time = 0;
|
|
|
|
int size = ArraySize(Positions);
|
|
for(int i = 0;i < size;i++)
|
|
{
|
|
ulong pos = Positions[i];
|
|
//Print("Position sell = ",pos);
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_SELL) continue;
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
datetime pos_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
|
|
if(last_pos == LAST_POSITION_DOWN)
|
|
{
|
|
if(open == 0 || pos_open < open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_UP)
|
|
{
|
|
if(open == 0 || pos_open > open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_TIME)
|
|
{
|
|
if(time == 0 || pos_time > time)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ticket;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
|
|
double GetComission(ulong position)
|
|
{
|
|
if(!HistorySelectByPosition(position)) return 0;
|
|
double comm = 0;
|
|
int tot_deals = HistoryDealsTotal();
|
|
for(int i = 0;i < tot_deals;i++)
|
|
{
|
|
ulong deal = HistoryDealGetTicket(i);
|
|
comm += HistoryDealGetDouble(deal,DEAL_COMMISSION);
|
|
}
|
|
|
|
return comm;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
double Profit(ulong position, double out_comission, bool subtotals = false)
|
|
{
|
|
double total_profit = 0;
|
|
|
|
double profit = 0, swap = 0, comission = 0;
|
|
double volume = 0;
|
|
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
profit = PositionGetDouble(POSITION_PROFIT);
|
|
swap = PositionGetDouble(POSITION_SWAP);
|
|
volume = PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
|
|
if(HistorySelectByPosition(position))
|
|
{
|
|
int total_deals = HistoryDealsTotal();
|
|
for(int i = 0;i < total_deals;i++)
|
|
{
|
|
ulong deal = HistoryDealGetTicket(i);
|
|
if(subtotals)
|
|
{
|
|
profit += HistoryDealGetDouble(deal,DEAL_PROFIT);
|
|
swap += HistoryDealGetDouble(deal,DEAL_SWAP);
|
|
}
|
|
comission += HistoryDealGetDouble(deal,DEAL_COMMISSION);
|
|
}
|
|
}
|
|
|
|
total_profit = (profit + swap + comission) - out_comission * volume;
|
|
|
|
return NormalizeDouble(total_profit,2);
|
|
}
|
|
//+---------------------------------------------------------------+
|
|
double Profit_History(datetime begin_time , datetime end_time , string symbol , uint magic)
|
|
{
|
|
ulong Positions[];
|
|
MqlParam params[2];
|
|
params[0].type = TYPE_STRING;
|
|
params[0].string_value = symbol;
|
|
params[1].type = TYPE_UINT;
|
|
params[1].integer_value = magic;
|
|
|
|
GetPositionsTickets(params, Positions);
|
|
|
|
double total_profit = 0;
|
|
|
|
double profit = 0, swap = 0, comission = 0;
|
|
|
|
if(HistorySelect(begin_time,end_time))
|
|
{
|
|
for(int i = 0;i < HistoryDealsTotal();i++)
|
|
{
|
|
ulong deal = HistoryDealGetTicket(i);
|
|
|
|
string deal_symbol = HistoryDealGetString(deal,DEAL_SYMBOL);
|
|
ulong deal_magic = HistoryDealGetInteger(deal,DEAL_MAGIC);
|
|
|
|
if(deal_symbol == symbol && deal_magic == magic)
|
|
{
|
|
for(int z = 0;z < ArraySize(Positions);z++)
|
|
{
|
|
ulong deal_pos = HistoryDealGetInteger(deal,DEAL_POSITION_ID);
|
|
if(deal_pos == Positions[z])
|
|
{
|
|
deal = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(deal > 0) total_profit += HistoryDealGetDouble(deal,DEAL_PROFIT) + HistoryDealGetDouble(deal,DEAL_SWAP)
|
|
+ HistoryDealGetDouble(deal,DEAL_COMMISSION);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NormalizeDouble(total_profit,2);
|
|
}
|
|
//+---------------------------------------------------------------+
|
|
bool Close_Position(ulong position, int slipage)
|
|
{
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
string pos_symb = PositionGetString(POSITION_SYMBOL);
|
|
ulong pos_mag = PositionGetInteger(POSITION_MAGIC);
|
|
double pos_volume = PositionGetDouble(POSITION_VOLUME);
|
|
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
if(pos_type == POSITION_TYPE_BUY)
|
|
{
|
|
reqwest.price = SymbolInfoDouble(pos_symb,SYMBOL_BID);
|
|
reqwest.type = ORDER_TYPE_SELL;
|
|
}
|
|
else
|
|
{
|
|
reqwest.price = SymbolInfoDouble(pos_symb,SYMBOL_ASK);
|
|
reqwest.type = ORDER_TYPE_BUY;
|
|
}
|
|
|
|
reqwest.position = position;
|
|
reqwest.magic = pos_mag;
|
|
reqwest.symbol = pos_symb;
|
|
reqwest.volume = pos_volume;
|
|
reqwest.deviation = slipage;
|
|
reqwest.action = TRADE_ACTION_DEAL;
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Позиция №",position," не была закрыта. Ошибка№",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
else Print("Позиция №",position," не найдена.");
|
|
|
|
return false;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
bool SetTralLevel(ulong position , int tralLevel)
|
|
{
|
|
if(PositionSelectByTicket(position))
|
|
{
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
double pos_sl = PositionGetDouble(POSITION_SL);
|
|
string pos_symbol = PositionGetString(POSITION_SYMBOL);
|
|
int pos_magic = (int)PositionGetInteger(POSITION_MAGIC);
|
|
if(pos_type == POSITION_TYPE_BUY)
|
|
{
|
|
double close_price = SymbolInfoDouble(pos_symbol,SYMBOL_BID);
|
|
double point = SymbolInfoDouble(pos_symbol,SYMBOL_POINT);
|
|
if(close_price > pos_open)
|
|
{
|
|
double tral_level;
|
|
if(pos_sl < pos_open) tral_level = pos_open + tralLevel * point;
|
|
else tral_level = pos_sl + tralLevel * point;
|
|
int stop_level = (int)SymbolInfoInteger(pos_symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
if(DistPrices(close_price,tral_level,pos_symbol) < stop_level) tral_level = close_price - stop_level * point;
|
|
|
|
if(tral_level > pos_sl)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.position = position;
|
|
reqwest.action = TRADE_ACTION_SLTP;
|
|
reqwest.sl = tral_level;
|
|
reqwest.symbol = pos_symbol;
|
|
reqwest.magic = pos_magic;
|
|
|
|
if(OrderSend(reqwest,result)) return true;
|
|
else Print("Ошибка тралирования ",result.retcode);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
double close_price = SymbolInfoDouble(pos_symbol,SYMBOL_ASK);
|
|
double point = SymbolInfoDouble(pos_symbol,SYMBOL_POINT);
|
|
if(close_price < pos_open)
|
|
{
|
|
double tral_level;
|
|
if(pos_sl < pos_open) tral_level = pos_open - tralLevel * point;
|
|
else tral_level = pos_sl - tralLevel * point;
|
|
int stop_level = (int)SymbolInfoInteger(pos_symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
if(DistPrices(close_price,tral_level,pos_symbol) < stop_level) tral_level = close_price + stop_level * point;
|
|
|
|
if(tral_level > pos_sl)
|
|
{
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.position = position;
|
|
reqwest.action = TRADE_ACTION_SLTP;
|
|
reqwest.sl = tral_level;
|
|
reqwest.symbol = pos_symbol;
|
|
reqwest.magic = pos_magic;
|
|
|
|
if(OrderSend(reqwest,result)) return true;
|
|
else Print("Ошибка тралирования ",result.retcode);
|
|
}
|
|
else return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//+---------------------------------------------------------------+
|
|
|
|
bool Close_PartPosition(ulong position, int slipage, ulong opposing_pos)
|
|
{
|
|
if(!PositionSelectByTicket(position))
|
|
{
|
|
Print(__FUNCTION__," Не найдена позиция для закрытия");
|
|
return false;
|
|
}
|
|
uint pos_magic = (uint)PositionGetInteger(POSITION_MAGIC);
|
|
if(!PositionSelectByTicket(opposing_pos))
|
|
{
|
|
Print(__FUNCTION__," Не найдена встречная позиция");
|
|
return false;
|
|
}
|
|
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
reqwest.action = TRADE_ACTION_CLOSE_BY;
|
|
reqwest.deviation = slipage;
|
|
reqwest.position = position;
|
|
reqwest.position_by = opposing_pos;
|
|
reqwest.magic = pos_magic;
|
|
|
|
if(OrderSend(reqwest,result)) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
/*double GetAveragePrice(const ulong &positions[], string symbol, double out_comm)
|
|
{
|
|
double totVolume = 0, totOpVolume = 0, totSwapCom = 0;
|
|
int koef = 1;
|
|
|
|
for(int i = 0,size = ::ArraySize(positions);i < size;i++)
|
|
{
|
|
if(!::PositionSelectByTicket(positions[i])) continue;
|
|
if(::PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) koef = 1;
|
|
else if(::PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) koef = -1;
|
|
|
|
double volume = ::PositionGetDouble(POSITION_VOLUME);
|
|
double op = ::PositionGetDouble(POSITION_PRICE_OPEN);
|
|
totOpVolume += (volume * op * koef);
|
|
totVolume += (volume * koef);
|
|
//double commission = GetComission(positions[i]);
|
|
totSwapCom += ::PositionGetDouble(POSITION_SWAP) /*+ commission *//*- out_comm * volume;*/
|
|
/*}
|
|
if(totVolume == 0) return 0;
|
|
|
|
double AvPrice = ::MathAbs(totOpVolume / totVolume);
|
|
double point = ::SymbolInfoDouble(symbol,SYMBOL_POINT);
|
|
if(totVolume > 0) AvPrice -= (totSwapCom / ::MathAbs(totVolume) * point);
|
|
if(totVolume < 0) AvPrice += (totSwapCom / ::MathAbs(totVolume) * point);
|
|
|
|
return ::NormalizeDouble(AvPrice,(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS));
|
|
}*/
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
double GetPointValue(string symbol)
|
|
{
|
|
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
|
|
double tickValue = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE);
|
|
double tickSize = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
|
|
double pointValue = tickValue * (point / tickSize);
|
|
return pointValue;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
//flag = 0 - All volume; 1 - BUY only; 2 - SELL only
|
|
double GetTotalVolume(const ulong &positions[], int flag = 0)
|
|
{
|
|
double tot_volume = 0;
|
|
for(int i = 0,size = ArraySize(positions);i < size;i++)
|
|
{
|
|
if(!PositionSelectByTicket(positions[i])) continue;
|
|
if(flag == 0) tot_volume += PositionGetDouble(POSITION_VOLUME);
|
|
else
|
|
{
|
|
if(flag == 1)
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) tot_volume += PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
else if(flag == 2)
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) tot_volume += PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
}
|
|
}
|
|
|
|
return tot_volume;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
int GetIntFromDouble(double value, int digits)
|
|
{
|
|
int result = 0;
|
|
if(digits == 1) result = (int)(value * 10);
|
|
else if(digits == 2) result = (int)(value * 100);
|
|
else if(digits == 3) result = (int)(value * 1000);
|
|
else if(digits == 4) result = (int)(value * 10000);
|
|
else if(digits == 5) result = (int)(value * 100000);
|
|
|
|
return result;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
double GetDoubleFromInt(int value,int digits)
|
|
{
|
|
double result = 0.0;
|
|
if(digits == 1) result = value * 0.1;
|
|
else if(digits == 2) result = value * 0.01;
|
|
else if(digits == 3) result = value * 0.001;
|
|
else if(digits == 4) result = value * 0.0001;
|
|
else if(digits == 5) result = value * 0.00001;
|
|
|
|
return NormalizeDouble(result,digits);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
double CostPoint(string symbol, double volume, ENUM_POSITION_TYPE type)
|
|
{
|
|
double price = SymbolInfoDouble(symbol, SYMBOL_BID);
|
|
if(type == POSITION_TYPE_SELL) price = SymbolInfoDouble(symbol, SYMBOL_ASK);
|
|
if (price == 0) {
|
|
PrintFormat("%s / ERROR: Добавьте в 'Обор рынка' %s", __FUNCTION__, symbol);
|
|
return 0;
|
|
}
|
|
|
|
// определяем вспомогательные данные
|
|
string xxx = StringSubstr(symbol, 0, 3);
|
|
string yyy = StringSubstr(symbol, 3, 3);
|
|
string tile = (StringLen(symbol) > 6) ? StringSubstr(symbol, 6) : "";
|
|
double contract = volume * SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
|
|
double costPoint = contract * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
|
|
|
|
// определяем цену одного пункта
|
|
if (yyy == "USD"); // обратная котировка
|
|
// ничего не делаем
|
|
else if (xxx == "USD") // прямая котировка
|
|
costPoint = costPoint / price;
|
|
else { // кросс-курс
|
|
string symbol1 = yyy + "USD" + tile;
|
|
price = SymbolInfoDouble(symbol1, SYMBOL_BID);
|
|
if(type == POSITION_TYPE_SELL) price = SymbolInfoDouble(symbol, SYMBOL_ASK);
|
|
if (price > 0) costPoint = costPoint * price;
|
|
else {
|
|
string symbol2 = "USD" + yyy + tile;
|
|
price = SymbolInfoDouble(symbol2, SYMBOL_BID);
|
|
if(type == POSITION_TYPE_SELL) price = SymbolInfoDouble(symbol, SYMBOL_ASK);
|
|
if (price == 0) {
|
|
PrintFormat("%s: Добавьте в 'Обор рынка' %s или %s", __FUNCTION__, symbol1, symbol2);
|
|
return 0;
|
|
}
|
|
costPoint = costPoint / price;
|
|
}
|
|
}
|
|
|
|
return costPoint;
|
|
}
|
|
|
|
//+---------------------------------------------------------------+
|
|
|
|
bool Close_PartPosition(ulong position, double close_volume, int slipage)
|
|
{
|
|
ResetLastError();
|
|
|
|
if(!PositionSelectByTicket(position))
|
|
{
|
|
Print(__FUNCTION__," не смогла найти закрываемую позицию. Ошибка ",GetLastError());
|
|
return false;
|
|
}
|
|
string symbol = PositionGetString(POSITION_SYMBOL);
|
|
uint magic = (uint)PositionGetInteger(POSITION_MAGIC);
|
|
double lot = PositionGetDouble(POSITION_VOLUME);
|
|
if(lot > close_volume) lot = close_volume;
|
|
|
|
MqlTradeRequest reqwest;
|
|
MqlTradeResult result;
|
|
ZeroMemory(reqwest);
|
|
ZeroMemory(result);
|
|
|
|
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
|
|
{
|
|
reqwest.type = ORDER_TYPE_SELL;
|
|
reqwest.price = SymbolInfoDouble(symbol,SYMBOL_BID);
|
|
}
|
|
else
|
|
{
|
|
reqwest.type = ORDER_TYPE_BUY;
|
|
reqwest.price = SymbolInfoDouble(symbol,SYMBOL_ASK);
|
|
}
|
|
reqwest.action = TRADE_ACTION_DEAL;
|
|
reqwest.position = position;
|
|
reqwest.symbol = symbol;
|
|
reqwest.volume = lot;
|
|
reqwest.magic = magic;
|
|
reqwest.deviation = slipage;
|
|
|
|
for(int i = 0;i < 10;i++)
|
|
{
|
|
if(!OrderSend(reqwest,result))
|
|
{
|
|
Print("Частичное закрытие не удалось. Ошибка сервера ",result.retcode);
|
|
Sleep(500);
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//+---------------------------------------------------------------+
|
|
|
|
ulong Ticket_Last_Buy(const ulong &Positions[] , LAST_POSITION_OPTION last_pos, const ulong ex_pos)
|
|
{
|
|
ulong ticket = 0;
|
|
double open = 0;
|
|
datetime time = 0;
|
|
|
|
int size = ArraySize(Positions);
|
|
for(int i = 0;i < size;i++)
|
|
{
|
|
ulong pos = Positions[i];
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
|
|
if(PositionGetInteger(POSITION_TICKET) == ex_pos) continue;
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
datetime pos_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
|
|
if(last_pos == LAST_POSITION_DOWN)
|
|
{
|
|
if(open == 0 || pos_open < open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_UP)
|
|
{
|
|
if(open == 0 || pos_open > open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_TIME)
|
|
{
|
|
if(time == 0 || pos_time > time)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ticket;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Ticket_Last_Sell(const ulong &Positions[] , LAST_POSITION_OPTION last_pos, const ulong ex_pos)
|
|
{
|
|
ulong ticket = 0;
|
|
double open = 0;
|
|
datetime time = 0;
|
|
|
|
int size = ArraySize(Positions);
|
|
for(int i = 0;i < size;i++)
|
|
{
|
|
ulong pos = Positions[i];
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_SELL) continue;
|
|
if(PositionGetInteger(POSITION_TICKET) == ex_pos) continue;
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
datetime pos_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
|
|
if(last_pos == LAST_POSITION_DOWN)
|
|
{
|
|
if(open == 0 || pos_open < open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_UP)
|
|
{
|
|
if(open == 0 || pos_open > open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_TIME)
|
|
{
|
|
if(time == 0 || pos_time > time)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ticket;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
ulong Ticket_Last_Buy(const ulong &Positions[] , LAST_POSITION_OPTION last_pos, const double ex_volume)
|
|
{
|
|
ulong ticket = 0;
|
|
double open = 0;
|
|
datetime time = 0;
|
|
|
|
int size = ArraySize(Positions);
|
|
for(int i = 0;i < size;i++)
|
|
{
|
|
ulong pos = Positions[i];
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
|
|
if(PositionGetDouble(POSITION_VOLUME) <= ex_volume) continue;
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
datetime pos_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
|
|
if(last_pos == LAST_POSITION_DOWN)
|
|
{
|
|
if(open == 0 || pos_open < open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_UP)
|
|
{
|
|
if(open == 0 || pos_open > open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_TIME)
|
|
{
|
|
if(time == 0 || pos_time > time)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ticket;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
ulong Ticket_Last_Sell(const ulong &Positions[] , LAST_POSITION_OPTION last_pos, const double ex_volume)
|
|
{
|
|
ulong ticket = 0;
|
|
double open = 0;
|
|
datetime time = 0;
|
|
|
|
int size = ArraySize(Positions);
|
|
for(int i = 0;i < size;i++)
|
|
{
|
|
ulong pos = Positions[i];
|
|
if(PositionSelectByTicket(pos))
|
|
{
|
|
if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_SELL) continue;
|
|
if(PositionGetDouble(POSITION_VOLUME) <= ex_volume) continue;
|
|
double pos_open = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
datetime pos_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
|
|
if(last_pos == LAST_POSITION_DOWN)
|
|
{
|
|
if(open == 0 || pos_open < open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_UP)
|
|
{
|
|
if(open == 0 || pos_open > open)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
else if(last_pos == LAST_POSITION_TIME)
|
|
{
|
|
if(time == 0 || pos_time > time)
|
|
{
|
|
open = pos_open;
|
|
time = pos_time;
|
|
ticket = pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ticket;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
/*double GetAveragePrice(const ulong &Positions[],string symbol,ENUM_POSITION_TYPE type,const double out_com)
|
|
{
|
|
for(int i = 0,size = ArraySize(Positions);i < size;i++)
|
|
{
|
|
if(!PositionSelectByTicket(Positions[i])) return 0;
|
|
if(PositionGetInteger(POSITION_TYPE) != type) return 0;
|
|
}
|
|
double AvPrice = 0;
|
|
return AvPrice;
|
|
}*/
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
enum ENUM_AVERAGE_DIRECTION
|
|
{
|
|
AVERAGE_DIRECTION_ALL = 0,
|
|
AVERAGE_DIRECTION_BUY,
|
|
AVERAGE_DIRECTION_SELL
|
|
};
|
|
|
|
double GetAveragePrice(const ulong &Positions[],
|
|
const double out_com,
|
|
ENUM_AVERAGE_DIRECTION avDirection = AVERAGE_DIRECTION_ALL)
|
|
{
|
|
string symbol = "";
|
|
for(int i = 0,size = ArraySize(Positions);i < size;i++)
|
|
{
|
|
if(!PositionSelectByTicket(Positions[i])) return 0;
|
|
if(symbol == "") symbol = PositionGetString(POSITION_SYMBOL);
|
|
else if(symbol == PositionGetString(POSITION_SYMBOL)) continue;
|
|
else if (symbol != "" && symbol != PositionGetString(POSITION_SYMBOL)) return 0;
|
|
}
|
|
|
|
double buyVolume = 0, sellVolume = 0, buyProfit = 0, sellProfit = 0;
|
|
for(int i = 0,size = ArraySize(Positions);i < size;i++)
|
|
{
|
|
PositionSelectByTicket(Positions[i]);
|
|
double lot = PositionGetDouble(POSITION_VOLUME);
|
|
double profit = PositionGetDouble(POSITION_PROFIT);
|
|
double swap = PositionGetDouble(POSITION_SWAP);
|
|
double comission = GetComission(Positions[i]) + ((out_com * -1) * lot);
|
|
double posProfit = profit + swap + comission;
|
|
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
|
|
{
|
|
buyVolume += lot;
|
|
buyProfit += posProfit;
|
|
}
|
|
else
|
|
{
|
|
sellVolume += lot;
|
|
sellProfit += posProfit;
|
|
}
|
|
}
|
|
if(avDirection == AVERAGE_DIRECTION_ALL && buyVolume == sellVolume) return 0;
|
|
else if(avDirection == AVERAGE_DIRECTION_BUY && buyVolume == 0) return 0;
|
|
else if(avDirection == AVERAGE_DIRECTION_SELL && sellVolume == 0) return 0;
|
|
|
|
double avPrice = 0;
|
|
double tickValue = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE);
|
|
int digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
|
|
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
|
|
double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
|
|
double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
|
|
|
|
double buyZeroLevel = bid - (buyProfit / (tickValue * buyVolume) * point);
|
|
double sellZeroLevel = ask + (sellProfit / (tickValue * sellVolume) * point);
|
|
buyZeroLevel = NormalizeDouble(buyZeroLevel,digits);
|
|
sellZeroLevel = NormalizeDouble(sellZeroLevel,digits);
|
|
if(buyVolume > sellVolume) avPrice = bid - ((buyProfit + sellProfit) / (tickValue * (buyVolume - sellVolume)) * point);
|
|
else avPrice = ask + ((buyProfit + sellProfit) / (tickValue * (sellVolume - buyVolume)) * point);
|
|
avPrice = NormalizeDouble(avPrice,digits);
|
|
|
|
if(avDirection == AVERAGE_DIRECTION_BUY) return buyZeroLevel;
|
|
else if(avDirection == AVERAGE_DIRECTION_SELL) return sellZeroLevel;
|
|
else return avPrice;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
template<typename T>
|
|
string GetTypeName(const T &t){
|
|
return (typename(T));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
template<typename T>
|
|
bool fileWriteBinStuct(const string &file, const T &fiboStruct){
|
|
int handle =::FileOpen(file,FILE_WRITE|FILE_BIN);
|
|
::ResetLastError();
|
|
if(handle == INVALID_HANDLE){
|
|
::Print("Unable acces to file ",file," Error ",::GetLastError());
|
|
return false;
|
|
}
|
|
|
|
uint count = ::FileWriteStruct(handle,fiboStruct);
|
|
if(count == 0){
|
|
::Print("Unable write data to file ",file," Error ",::GetLastError());
|
|
return false;
|
|
}
|
|
::FileClose(handle);
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
template<typename T>
|
|
bool fileReadBinStuct(const string &file, T &Struct){
|
|
int handle =::FileOpen(file,FILE_READ|FILE_BIN);
|
|
::ResetLastError();
|
|
if(handle == INVALID_HANDLE){
|
|
::Print("Unable acces to file ",file," Error ",::GetLastError());
|
|
return false;
|
|
}
|
|
|
|
uint count = ::FileReadStruct(handle,Struct);
|
|
if(count == 0){
|
|
::Print("Unable read data from file ",file," Error ",::GetLastError());
|
|
return false;
|
|
}
|
|
::FileClose(handle);
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
void GetFillMode(const string symbol,ENUM_ORDER_TYPE_FILLING &fill_type){
|
|
|
|
uint filling = (uint)::SymbolInfoInteger(symbol,SYMBOL_FILLING_MODE);
|
|
if((filling&SYMBOL_FILLING_FOK) == SYMBOL_FILLING_FOK)
|
|
fill_type = ORDER_FILLING_FOK;
|
|
else if((filling&SYMBOL_FILLING_IOC) == SYMBOL_FILLING_IOC)
|
|
fill_type = ORDER_FILLING_IOC;
|
|
else
|
|
fill_type = ORDER_FILLING_RETURN;
|
|
}
|
|
|
|
//------------------------------------------------------------------|
|
|
// END OF NAMESPACE std |
|
|
//------------------------------------------------------------------|
|
|
|
|
}
|
|
|
|
#endif |