610 lines
No EOL
46 KiB
MQL5
610 lines
No EOL
46 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ExpertMM1.mq5 |
|
|
//| Copyright 2024, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
#property description "Exemplo de EA"
|
|
|
|
#include <Trade\PositionInfo.mqh> //Instatiate Library for Positions Information
|
|
#include <Trade\Trade.mqh>
|
|
#include <Trade\AccountInfo.mqh>
|
|
|
|
input double lots=0.01; // volume em lotes
|
|
input int slippage=10; // derrapagem admissível
|
|
input bool revers=false; // invertemos o sinal?
|
|
input ulong EXPERT_MAGIC=0; // MagicNumber do EA
|
|
double trade_lot;
|
|
double lastAskHit;
|
|
CTrade m_trade; // Trades Info and Executions library
|
|
COrderInfo m_order; //Library for Orders information
|
|
CPositionInfo m_position; // Library for all position features and information
|
|
CAccountInfo m_account;
|
|
double OpenVolume=0;
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//--- definimos o volume correto
|
|
double min_lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
|
|
trade_lot=lots>min_lot? lots:min_lot;
|
|
//--- criamos o identificador do indicador ATR
|
|
//--- inicialização bem-sucedida do EA
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//--- relatamos o código de desligamento do EA
|
|
Print(__FILE__,": Código de motivo da desinicialização = ",reason);
|
|
//--- destroy timer
|
|
EventKillTimer();
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
|
|
void OnTick()
|
|
{
|
|
double dailyHigh = iHigh(Symbol(), PERIOD_M15, 1); // Get the daily high
|
|
double dailyLow = iLow(Symbol(), PERIOD_M15, 1); // Get the daily low
|
|
double bidPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID); // Get the current Bid price
|
|
double askPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK); // Get the current Ask price
|
|
|
|
if(m_account.MarginLevel() < 200)
|
|
CloseAllPositions();
|
|
if(GetAccountOpenPositions(Symbol())>0.20 || GetAccountOpenPositions(Symbol())<-0.20 )
|
|
CloseAllPositions();
|
|
|
|
if(isNewBar())
|
|
{
|
|
|
|
// Check if there are no open positions
|
|
MqlTradeRequest request;
|
|
MqlTradeResult result;
|
|
ZeroMemory(request);
|
|
|
|
request.action = TRADE_ACTION_DEAL;
|
|
request.symbol = Symbol();
|
|
request.volume = 0.01; // Fixed lot size 0.01
|
|
request.deviation = 20; // Increased slippage tolerance
|
|
request.magic = EXPERT_MAGIC; // Use user-defined Magic Number
|
|
request.comment = "Daily High/Low EA";
|
|
|
|
// Set order filling mode dynamically
|
|
ENUM_ORDER_TYPE_FILLING fillingMode;
|
|
if (SymbolInfoInteger(Symbol(), SYMBOL_FILLING_MODE) & SYMBOL_FILLING_IOC)
|
|
fillingMode = ORDER_FILLING_IOC;
|
|
else
|
|
fillingMode = ORDER_FILLING_RETURN;
|
|
|
|
request.type_filling = fillingMode;
|
|
request.type_time = ORDER_TIME_GTC; // Good till canceled
|
|
|
|
// ✅ Buy condition: Ask price reaches near the daily high
|
|
if (askPrice >= dailyHigh & GetAccountOpenPositions(Symbol())<=0)
|
|
{
|
|
//if(GetAccountOpenPositions(Symbol())>0)
|
|
// CloseAllPositions();
|
|
request.type = ORDER_TYPE_SELL;
|
|
request.price = askPrice; // Buying at Ask price
|
|
request.sl = askPrice + 100 * Point();
|
|
Print("Placing BUY order at Ask: ", askPrice);
|
|
// Send the order
|
|
if (!OrderSend(request, result))
|
|
Print("Trade execution error: ", result.comment);
|
|
else
|
|
Print("Order placed: ", result.price, " | Magic Number: ", EXPERT_MAGIC);
|
|
}
|
|
// ✅ Sell condition: Bid price reaches near the daily low
|
|
else if (bidPrice <= dailyLow & GetAccountOpenPositions(Symbol())>=0)
|
|
{
|
|
///if(GetAccountOpenPositions(Symbol())<0)
|
|
//CloseAllPositions();
|
|
request.type = ORDER_TYPE_BUY;
|
|
request.price = bidPrice; // Selling at Bid price;
|
|
request.sl = request.price - 100 * Point();
|
|
Print("Placing SELL order at Bid: ", bidPrice);
|
|
// Send the order
|
|
if (!OrderSend(request, result))
|
|
Print("Trade execution error: ", result.comment);
|
|
else
|
|
Print("Order placed: ", result.price, " | Magic Number: ", EXPERT_MAGIC);
|
|
}
|
|
else
|
|
return; // No trade condition met
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Trade function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTrade()
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| TradeTransaction function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
|
const MqlTradeRequest& request,
|
|
const MqlTradeResult& result)
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Tester function |
|
|
//+------------------------------------------------------------------+
|
|
double OnTester()
|
|
{
|
|
//---
|
|
double ret=0.0;
|
|
//---
|
|
|
|
//---
|
|
return(ret);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| TesterInit function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTesterInit()
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| TesterPass function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTesterPass()
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| TesterDeinit function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTesterDeinit()
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| ChartEvent function |
|
|
//+------------------------------------------------------------------+
|
|
void OnChartEvent(const int id,
|
|
const long &lparam,
|
|
const double &dparam,
|
|
const string &sparam)
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns true if a new bar has appeared for a symbol/period pair |
|
|
//+------------------------------------------------------------------+
|
|
bool isNewBar()
|
|
{
|
|
//--- memorize the time of opening of the last bar in the static variable
|
|
static datetime last_time=0;
|
|
//--- current time
|
|
datetime lastbar_time=SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
|
|
|
|
//--- if it is the first call of the function
|
|
if(last_time==0)
|
|
{
|
|
//--- set the time and exit
|
|
last_time=lastbar_time;
|
|
return(false);
|
|
}
|
|
|
|
//--- if the time differs
|
|
if(last_time!=lastbar_time)
|
|
{
|
|
//--- memorize the time and return true
|
|
last_time=lastbar_time;
|
|
return(true);
|
|
}
|
|
//--- if we passed to this line, then the bar is not new; return false
|
|
return(false);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns type of a pending order in a random way |
|
|
//+------------------------------------------------------------------+
|
|
ENUM_ORDER_TYPE GetRandomType()
|
|
{
|
|
int t=MathRand()%2;
|
|
//--- 0<=t<4
|
|
switch(t)
|
|
{
|
|
case(0):return(ORDER_TYPE_BUY_LIMIT);
|
|
case(1):return(ORDER_TYPE_SELL_LIMIT);
|
|
}
|
|
//--- incorrect value
|
|
return(WRONG_VALUE);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Deletes all pending orders with specified ORDER_MAGIC |
|
|
//+------------------------------------------------------------------+
|
|
void DeleteAllOrdersByMagic(long const magic_number)
|
|
{
|
|
ulong order_ticket;
|
|
//--- go through all pending orders
|
|
for(int i=OrdersTotal()-1;i>=0;i--)
|
|
if((order_ticket=OrderGetTicket(i))>0)
|
|
//--- order with appropriate ORDER_MAGIC
|
|
if(magic_number==OrderGetInteger(ORDER_MAGIC))
|
|
{
|
|
MqlTradeResult result={};
|
|
MqlTradeRequest request={};
|
|
request.order=order_ticket;
|
|
request.action=TRADE_ACTION_REMOVE;
|
|
OrderSend(request,result);
|
|
//--- write the server reply to log
|
|
Print(__FUNCTION__,": ",result.comment," reply code ",result.retcode);
|
|
}
|
|
//---
|
|
}
|
|
|
|
int GetOrdersTotalByMagic(long const magic_number)
|
|
{
|
|
ulong order_ticket;
|
|
int total=0;
|
|
//--- go through all pending orders
|
|
for(int i=0;i<OrdersTotal();i++)
|
|
if((order_ticket=OrderGetTicket(i))>0)
|
|
if(magic_number==OrderGetInteger(ORDER_MAGIC)) total++;
|
|
//---
|
|
return(total);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buy at a market price with a specified volume |
|
|
//+------------------------------------------------------------------+
|
|
bool Buy(double volume,ulong deviation=10,ulong magicnumber=0)
|
|
{
|
|
//--- buy at a market price
|
|
return (MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Sell at a market price with a specified volume |
|
|
//+------------------------------------------------------------------+
|
|
bool Sell(double volume,ulong deviation=10,ulong magicnumber=0)
|
|
{
|
|
//--- sell at a market price
|
|
return (MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber));
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sets a pending order in a random way |
|
|
//+------------------------------------------------------------------+
|
|
uint SendRandomPendingOrder(long const magic_number)
|
|
{
|
|
//--- prepare a request
|
|
MqlTradeRequest request={};
|
|
request.action=TRADE_ACTION_PENDING; // setting a pending order
|
|
request.magic=magic_number; // ORDER_MAGIC
|
|
request.symbol=_Symbol; // symbol
|
|
request.volume=0.01; // volume in 0.01 lots
|
|
request.sl=0;
|
|
request.tp=0; // Take Profit is not specified
|
|
//--- form the order type
|
|
request.type=GetRandomType(); // order type
|
|
//request.type=ORDER_TYPE_BUY_LIMIT;
|
|
//--- form the price for the pending order
|
|
request.price=GetRandomPrice(request.type); // open price
|
|
if(request.type==ORDER_TYPE_BUY_LIMIT)
|
|
{
|
|
request.tp=iHigh(Symbol(),PERIOD_D1,0);
|
|
request.sl=iLow(Symbol(),PERIOD_D1,0);
|
|
}
|
|
else
|
|
if(request.type==ORDER_TYPE_SELL_LIMIT) // ORDER_TYPE_SELL_LIMIT or ORDER_TYPE_BUY_STOP
|
|
{
|
|
request.tp=iLow(Symbol(),PERIOD_D1,0);
|
|
request.sl=iHigh(Symbol(),PERIOD_D1,0);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
//--- send a trade request
|
|
MqlTradeResult result={};
|
|
OrderSend(request,result);
|
|
//--- write the server reply to log
|
|
Print(__FUNCTION__,":",result.comment);
|
|
if(result.retcode==10016) Print(result.bid,result.ask,result.price);
|
|
//--- return code of the trade server reply
|
|
return result.retcode;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Prepare and send a trade request |
|
|
//+------------------------------------------------------------------+
|
|
bool MarketOrder(ENUM_ORDER_TYPE type,double volume,ulong slip,ulong magicnumber,ulong pos_ticket=0)
|
|
{
|
|
//--- declaring and initializing structures
|
|
MqlTradeRequest request={};
|
|
MqlTradeResult result={};
|
|
double price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
|
|
if(type==ORDER_TYPE_BUY)
|
|
price=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
|
|
if(type==ORDER_TYPE_BUY_LIMIT)
|
|
price=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
|
|
if(type==ORDER_TYPE_SELL)
|
|
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
|
|
if(type==ORDER_TYPE_SELL_LIMIT)
|
|
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
|
|
//--- request parameters
|
|
request.action =TRADE_ACTION_DEAL; // trading operation type
|
|
request.position =pos_ticket; // position ticket if closing
|
|
request.symbol =Symbol(); // symbol
|
|
request.volume =volume; // volume
|
|
request.type =type; // order type
|
|
request.price =price; // trade price
|
|
request.deviation=slip; // allowable deviation from the price
|
|
request.magic =magicnumber; // order MagicNumber
|
|
//--- send a request
|
|
if(!OrderSend(request,result))
|
|
{
|
|
//--- display data on failure
|
|
PrintFormat("OrderSend %s %s %.2f at %.5f error %d",
|
|
request.symbol,EnumToString(type),volume,request.price,GetLastError());
|
|
return (false);
|
|
}
|
|
//--- inform of a successful operation
|
|
PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
|
|
return (true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns price in a random way |
|
|
//+------------------------------------------------------------------+
|
|
double GetRandomPrice(ENUM_ORDER_TYPE type)
|
|
{
|
|
int t=(int)type;
|
|
//--- stop levels for the symbol
|
|
int distance=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
if(distance<=0)
|
|
distance=150;
|
|
else
|
|
distance+=50;
|
|
//--- receive data of the last tick
|
|
MqlTick last_tick={};
|
|
SymbolInfoTick(_Symbol,last_tick);
|
|
//--- calculate price according to the type
|
|
double price;
|
|
if(t==ORDER_TYPE_BUY_LIMIT ) // ORDER_TYPE_BUY_LIMIT or ORDER_TYPE_SELL_STOP
|
|
{
|
|
price=last_tick.bid; // depart from price Bid
|
|
price=price-distance*_Point;
|
|
}
|
|
else
|
|
if(t==ORDER_TYPE_SELL_LIMIT ) // ORDER_TYPE_SELL_LIMIT or ORDER_TYPE_BUY_STOP
|
|
{
|
|
price=last_tick.ask; // depart from price Ask
|
|
price=price+distance*_Point;
|
|
}
|
|
//---
|
|
return(price);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Close all positions |
|
|
//+------------------------------------------------------------------+
|
|
void CloseAllPositions()
|
|
{
|
|
for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions
|
|
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
|
|
m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Is position exists |
|
|
//+------------------------------------------------------------------+
|
|
bool IsPositionExists(void)
|
|
{
|
|
for(int i=PositionsTotal()-1;i>=0;i--)
|
|
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
|
|
return(true);
|
|
//---
|
|
return(false);
|
|
}
|
|
|
|
|
|
bool CheckMoneyForTrade(string symb,double lot,ENUM_ORDER_TYPE type)
|
|
{
|
|
//--- Getting the opening price
|
|
MqlTick mqltick;
|
|
SymbolInfoTick(symb,mqltick);
|
|
double price=mqltick.ask;
|
|
if(type==ORDER_TYPE_SELL)
|
|
price=mqltick.bid;
|
|
//--- values of the required and free margin
|
|
double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
|
|
//--- call of the checking function
|
|
if(!OrderCalcMargin(type,symb,lot,price,margin))
|
|
{
|
|
//--- something went wrong, report and return false
|
|
Print("Error in ",__FUNCTION__," code=",GetLastError());
|
|
return(false);
|
|
}
|
|
//--- if there are insufficient funds to perform the operation
|
|
if(margin>free_margin)
|
|
{
|
|
//--- report the error and return false
|
|
Print("Not enough money for ",EnumToString(type)," ",lot," ",symb," Error code=",GetLastError());
|
|
return(false);
|
|
}
|
|
//--- checking successful
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check the correctness of the order volume |
|
|
//+------------------------------------------------------------------+
|
|
bool CheckVolumeValue(double volume,string &description)
|
|
{
|
|
//--- minimal allowed volume for trade operations
|
|
double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
|
|
if(volume<min_volume)
|
|
{
|
|
description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
|
|
return(false);
|
|
}
|
|
|
|
//--- maximal allowed volume of trade operations
|
|
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
|
|
if(volume>max_volume)
|
|
{
|
|
description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
|
|
return(false);
|
|
}
|
|
|
|
//--- get minimal step of volume changing
|
|
double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
|
|
|
|
int ratio=(int)MathRound(volume/volume_step);
|
|
if(MathAbs(ratio*volume_step-volume)>0.0000001)
|
|
{
|
|
description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
|
|
volume_step,ratio*volume_step);
|
|
return(false);
|
|
}
|
|
description="Correct volume value";
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check if another order can be placed |
|
|
//+------------------------------------------------------------------+
|
|
bool IsNewOrderAllowed()
|
|
{
|
|
//--- get the number of pending orders allowed on the account
|
|
int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);
|
|
|
|
//--- if there is no limitation, return true; you can send an order
|
|
if(max_allowed_orders==0) return(true);
|
|
|
|
//--- if we passed to this line, then there is a limitation; find out how many orders are already placed
|
|
int orders=OrdersTotal();
|
|
|
|
//--- return the result of comparing
|
|
return(orders<max_allowed_orders);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Return the size of position on the specified symbol |
|
|
//+------------------------------------------------------------------+
|
|
double PositionVolume(string symbol)
|
|
{
|
|
//--- try to select position by a symbol
|
|
bool selected=PositionSelect(symbol);
|
|
//--- there is a position
|
|
if(selected)
|
|
//--- return volume of the position
|
|
return(PositionGetDouble(POSITION_VOLUME));
|
|
else
|
|
{
|
|
//--- report a failure to select position
|
|
Print(__FUNCTION__," Failed to perform PositionSelect() for symbol ",
|
|
symbol," Error ",GetLastError());
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| returns the volume of current pending order by a symbol |
|
|
//+------------------------------------------------------------------+
|
|
double PendingsVolume(string symbol)
|
|
{
|
|
double volume_on_symbol=0;
|
|
ulong ticket;
|
|
//--- get the number of all currently placed orders by all symbols
|
|
int all_orders=OrdersTotal();
|
|
|
|
//--- get over all orders in the loop
|
|
for(int i=0;i<all_orders;i++)
|
|
{
|
|
//--- get the ticket of an order by its position in the list
|
|
ticket=OrderGetTicket(i);
|
|
//--- if our symbol is specified in the order, add the volume of this order
|
|
if(symbol==OrderGetString(ORDER_SYMBOL))
|
|
volume_on_symbol+=OrderGetDouble(ORDER_VOLUME_INITIAL);
|
|
}
|
|
//--- return the total volume of currently placed pending orders for a specified symbol
|
|
return(volume_on_symbol);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Return the maximum allowed volume for an order on the symbol |
|
|
//+------------------------------------------------------------------+
|
|
double NewOrderAllowedVolume(string symbol)
|
|
{
|
|
double allowed_volume=0;
|
|
//--- get the limitation on the maximal volume of an order
|
|
double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
|
|
//--- get the limitation on the volume by a symbol
|
|
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
|
|
|
|
//--- get the volume of the open position by a symbol
|
|
double opened_volume=PositionVolume(symbol);
|
|
if(opened_volume>=0)
|
|
{
|
|
//--- if we have exhausted the volume
|
|
if(max_volume-opened_volume<=0)
|
|
return(0);
|
|
|
|
//--- volume of the open position doesn't exceed max_volume
|
|
double orders_volume_on_symbol=PendingsVolume(symbol);
|
|
allowed_volume=max_volume-opened_volume-orders_volume_on_symbol;
|
|
if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume;
|
|
}
|
|
return(allowed_volume);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Return the volume open in symbol |
|
|
//+------------------------------------------------------------------+
|
|
|
|
double GetAccountOpenPositions(string symbol)
|
|
{
|
|
double totalVolume=0;
|
|
// Loop through all open positions and print their volume
|
|
int totalPositions = PositionsTotal(); // Get the total number of open positions
|
|
|
|
for (int i = 0; i < totalPositions; i++)
|
|
{
|
|
if (m_position.SelectByIndex(i)) // Select the position by index
|
|
{
|
|
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
|
|
totalVolume += PositionGetDouble(POSITION_VOLUME); // Get the volume of the position
|
|
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
|
|
totalVolume -= PositionGetDouble(POSITION_VOLUME); // Get the volume of the position
|
|
}
|
|
}
|
|
|
|
return totalVolume;
|
|
} |