* Add support for Buy Market, Sell Market, Buy Limit, Sell Limit, Buy Stop, and Sell Stop setups * Create adjustable Entry, Stop Loss, and Take Profit chart lines * Implement trade direction detection and setup validation * Add stop-loss distance calculation * Add risk amount calculation based on account balance percentage * Implement broker-aware position sizing and volume normalization * Add reward, risk-to-reward, and estimated profit calculations * Create real-time dashboard displaying position metrics * Add chart event handling for interactive line updates * Add market price synchronization for market order entry levels * Implement chart object lifecycle management and cleanup * Add ATR-based default line initialization * Add custom chart appearance and dashboard framework This commit establishes the core architecture of the Position Size Tool and lays the foundation for future enhancements and trade execution capabilities.
748 lines
25 KiB
MQL5
748 lines
25 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
|
//| PositionSizeTool.mq5 |
|
|
//| Copyright 2026, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com/en/users/ririeh |
|
|
//+------------------------------------------------------------------+
|
|
|
|
#property copyright "Copyright 2026, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com/en/users/ririeh"
|
|
#property version "1.00"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Position Line Object Names |
|
|
//+------------------------------------------------------------------+
|
|
#define ENTRY_LINE_NAME "PST_Entry_Line"
|
|
#define SL_LINE_NAME "PST_StopLoss_Line"
|
|
#define TP_LINE_NAME "PST_TakeProfit_Line"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Dashboard Object Prefix |
|
|
//+------------------------------------------------------------------+
|
|
#define PANEL_PREFIX "PST_Panel_"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Dashboard Settings |
|
|
//+------------------------------------------------------------------+
|
|
#define PANEL_BG_NAME "PST_Panel_Background"
|
|
#define PANEL_X 20
|
|
#define PANEL_Y 30
|
|
#define PANEL_WIDTH 280
|
|
#define PANEL_HEIGHT 285
|
|
#define PANEL_LINE_GAP 18
|
|
|
|
#define PANEL_TEXT clrWhite
|
|
#define PANEL_TITLE clrGold
|
|
#define PANEL_BG clrBlack
|
|
#define PANEL_BORDER clrDimGray
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Position Tool Order Types |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_POSITION_TOOL_ORDER_TYPE
|
|
{
|
|
PTO_BUY_MARKET = 0, // Buy Market
|
|
PTO_SELL_MARKET, // Sell Market
|
|
PTO_BUY_LIMIT, // Buy Limit
|
|
PTO_SELL_LIMIT, // Sell Limit
|
|
PTO_BUY_STOP, // Buy Stop
|
|
PTO_SELL_STOP // Sell Stop
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Position Tool Direction |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_POSITION_TOOL_DIRECTION
|
|
{
|
|
PTD_BUY = 0, // Buy setup
|
|
PTD_SELL // Sell setup
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns setup direction from selected order type |
|
|
//+------------------------------------------------------------------+
|
|
ENUM_POSITION_TOOL_DIRECTION GetSetupDirection()
|
|
{
|
|
switch(InpOrderType)
|
|
{
|
|
case PTO_BUY_MARKET:
|
|
case PTO_BUY_LIMIT:
|
|
case PTO_BUY_STOP:
|
|
return PTD_BUY;
|
|
|
|
case PTO_SELL_MARKET:
|
|
case PTO_SELL_LIMIT:
|
|
case PTO_SELL_STOP:
|
|
return PTD_SELL;
|
|
}
|
|
|
|
return PTD_BUY;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Position Size Tool Inputs |
|
|
//+------------------------------------------------------------------+
|
|
input ENUM_POSITION_TOOL_ORDER_TYPE InpOrderType = PTO_BUY_MARKET;
|
|
input double InpRiskPercent = 1.0;
|
|
input color InpEntryLineColor = clrDodgerBlue;
|
|
input color InpSLLineColor = clrTomato;
|
|
input color InpTPLineColor = clrLimeGreen;
|
|
|
|
input ENUM_TIMEFRAMES InpATRTimeframe = PERIOD_H1;
|
|
input int InpATRPeriod = 14;
|
|
input double InpSLATRFactor = 1.0;
|
|
input double InpTPATRFactor = 2.0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Position Prices |
|
|
//+------------------------------------------------------------------+
|
|
double EntryPrice = 0.0;
|
|
double StopLossPrice = 0.0;
|
|
double TakeProfitPrice = 0.0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
ConfigureChartAppearance();
|
|
|
|
ConfigureChartDisplay();
|
|
|
|
InitializeLinePrices();
|
|
|
|
if(!CreatePositionLines())
|
|
return INIT_FAILED;
|
|
|
|
CreateDashboard();
|
|
UpdateDashboard();
|
|
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
DeleteDashboard();
|
|
DeletePositionLines();
|
|
|
|
ChartRedraw(0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Tick event handler |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
UpdateMarketEntryPrice();
|
|
UpdateDashboard();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
//---
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Chart event handler |
|
|
//+------------------------------------------------------------------+
|
|
void OnChartEvent(const int id,
|
|
const long &lparam,
|
|
const double &dparam,
|
|
const string &sparam)
|
|
{
|
|
if(id != CHARTEVENT_OBJECT_DRAG)
|
|
return;
|
|
|
|
if(IsMarketOrderType() && sparam == ENTRY_LINE_NAME)
|
|
return;
|
|
|
|
if(sparam == ENTRY_LINE_NAME ||
|
|
sparam == SL_LINE_NAME ||
|
|
sparam == TP_LINE_NAME)
|
|
{
|
|
UpdateDashboard();
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Initializes default line prices |
|
|
//+------------------------------------------------------------------+
|
|
void InitializeLinePrices()
|
|
{
|
|
double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
|
|
double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
|
|
|
|
double atr = GetATRValue();
|
|
|
|
if(atr <= 0.0)
|
|
atr = 100 * _Point;
|
|
|
|
double slDistance = atr * InpSLATRFactor;
|
|
double tpDistance = atr * InpTPATRFactor;
|
|
|
|
switch(InpOrderType)
|
|
{
|
|
case PTO_BUY_MARKET:
|
|
EntryPrice = ask;
|
|
StopLossPrice = EntryPrice - slDistance;
|
|
TakeProfitPrice = EntryPrice + tpDistance;
|
|
break;
|
|
|
|
case PTO_SELL_MARKET:
|
|
EntryPrice = bid;
|
|
StopLossPrice = EntryPrice + slDistance;
|
|
TakeProfitPrice = EntryPrice - tpDistance;
|
|
break;
|
|
|
|
case PTO_BUY_LIMIT:
|
|
EntryPrice = bid - slDistance;
|
|
StopLossPrice = EntryPrice - slDistance;
|
|
TakeProfitPrice = EntryPrice + tpDistance;
|
|
break;
|
|
|
|
case PTO_SELL_LIMIT:
|
|
EntryPrice = ask + slDistance;
|
|
StopLossPrice = EntryPrice + slDistance;
|
|
TakeProfitPrice = EntryPrice - tpDistance;
|
|
break;
|
|
|
|
case PTO_BUY_STOP:
|
|
EntryPrice = ask + slDistance;
|
|
StopLossPrice = EntryPrice - slDistance;
|
|
TakeProfitPrice = EntryPrice + tpDistance;
|
|
break;
|
|
|
|
case PTO_SELL_STOP:
|
|
EntryPrice = bid - slDistance;
|
|
StopLossPrice = EntryPrice + slDistance;
|
|
TakeProfitPrice = EntryPrice - tpDistance;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Creates an adjustable horizontal price line |
|
|
//+------------------------------------------------------------------+
|
|
bool CreatePriceLine(string name,double price,color lineColor,string text)
|
|
{
|
|
ObjectDelete(0,name);
|
|
|
|
if(!ObjectCreate(0,name,OBJ_HLINE,0,0,price))
|
|
{
|
|
Print("Failed to create line: ",name," Error: ",GetLastError());
|
|
return false;
|
|
}
|
|
|
|
bool draggable = true;
|
|
|
|
if(name == ENTRY_LINE_NAME && IsMarketOrderType())
|
|
draggable = false;
|
|
|
|
ObjectMove(0,name,0,0,price);
|
|
|
|
ObjectSetInteger(0,name,OBJPROP_COLOR,lineColor);
|
|
ObjectSetInteger(0,name,OBJPROP_WIDTH,2);
|
|
ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
|
|
|
|
ObjectSetInteger(0,name,OBJPROP_BACK,false);
|
|
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,draggable);
|
|
ObjectSetInteger(0,name,OBJPROP_SELECTED,true);
|
|
ObjectSetInteger(0,name,OBJPROP_HIDDEN,false);
|
|
|
|
ObjectSetString(0,name,OBJPROP_TEXT,text);
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Creates all position tool lines |
|
|
//+------------------------------------------------------------------+
|
|
bool CreatePositionLines()
|
|
{
|
|
if(!CreatePriceLine(ENTRY_LINE_NAME,EntryPrice,InpEntryLineColor,"Entry"))
|
|
return false;
|
|
|
|
if(!CreatePriceLine(SL_LINE_NAME,StopLossPrice,InpSLLineColor,"Stop Loss"))
|
|
return false;
|
|
|
|
if(!CreatePriceLine(TP_LINE_NAME,TakeProfitPrice,InpTPLineColor,"Take Profit"))
|
|
return false;
|
|
|
|
ChartRedraw(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns the current price of a horizontal line |
|
|
//+------------------------------------------------------------------+
|
|
double GetLinePrice(string name)
|
|
{
|
|
if(ObjectFind(0,name) < 0)
|
|
return 0.0;
|
|
|
|
return ObjectGetDouble(0,name,OBJPROP_PRICE,0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Updates current line prices |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateLinePrices()
|
|
{
|
|
EntryPrice = GetLinePrice(ENTRY_LINE_NAME);
|
|
StopLossPrice = GetLinePrice(SL_LINE_NAME);
|
|
TakeProfitPrice = GetLinePrice(TP_LINE_NAME);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns direction text |
|
|
//+------------------------------------------------------------------+
|
|
string GetDirectionText()
|
|
{
|
|
ENUM_POSITION_TOOL_DIRECTION direction = GetSetupDirection();
|
|
|
|
if(direction == PTD_BUY)
|
|
return "Buy";
|
|
|
|
return "Sell";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculates stop loss distance in price and points |
|
|
//+------------------------------------------------------------------+
|
|
bool CalculateStopLossDistance(double &stopDistance,
|
|
double &stopPoints,
|
|
string &status)
|
|
{
|
|
stopDistance = MathAbs(EntryPrice - StopLossPrice);
|
|
stopPoints = stopDistance / _Point;
|
|
|
|
if(stopDistance <= 0.0)
|
|
{
|
|
status = "Invalid: Stop Loss distance must be greater than zero.";
|
|
return false;
|
|
}
|
|
|
|
status = "Valid stop loss distance.";
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculates risk amount from account balance |
|
|
//+------------------------------------------------------------------+
|
|
double CalculateRiskAmount()
|
|
{
|
|
double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
|
|
return accountBalance * InpRiskPercent / 100.0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Normalizes volume according to symbol trading rules |
|
|
//+------------------------------------------------------------------+
|
|
double NormalizeVolume(double volume)
|
|
{
|
|
double minVolume = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
|
|
double maxVolume = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
|
|
double volumeStep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
|
|
|
|
if(volume < minVolume)
|
|
volume = minVolume;
|
|
|
|
if(volume > maxVolume)
|
|
volume = maxVolume;
|
|
|
|
volume = MathFloor(volume / volumeStep) * volumeStep;
|
|
|
|
return NormalizeDouble(volume,2);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculates lot size from risk amount and stop loss distance |
|
|
//+------------------------------------------------------------------+
|
|
bool CalculateLotSize(double stopDistance,
|
|
double riskMoney,
|
|
double &lotSize,
|
|
string &status)
|
|
{
|
|
double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
|
|
double tickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
|
|
|
|
if(tickValue <= 0.0 || tickSize <= 0.0)
|
|
{
|
|
status = "Invalid: Tick value or tick size is unavailable.";
|
|
return false;
|
|
}
|
|
|
|
if(stopDistance <= 0.0)
|
|
{
|
|
status = "Invalid: Stop distance must be greater than zero.";
|
|
return false;
|
|
}
|
|
|
|
double moneyPerLot = stopDistance / tickSize * tickValue;
|
|
|
|
if(moneyPerLot <= 0.0)
|
|
{
|
|
status = "Invalid: Money risk per lot is zero.";
|
|
return false;
|
|
}
|
|
|
|
double rawLotSize = riskMoney / moneyPerLot;
|
|
|
|
lotSize = NormalizeVolume(rawLotSize);
|
|
|
|
status = "Lot size calculated.";
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculates reward distance, RR, and estimated reward |
|
|
//+------------------------------------------------------------------+
|
|
bool CalculateRewardMetrics(double stopPoints,
|
|
double riskMoney,
|
|
double &rewardPoints,
|
|
double &rr,
|
|
double &rewardMoney,
|
|
string &status)
|
|
{
|
|
double rewardDistance = MathAbs(TakeProfitPrice - EntryPrice);
|
|
rewardPoints = rewardDistance / _Point;
|
|
|
|
if(stopPoints <= 0.0)
|
|
{
|
|
status = "Invalid: Stop points must be greater than zero.";
|
|
return false;
|
|
}
|
|
|
|
if(rewardPoints <= 0.0)
|
|
{
|
|
status = "Invalid: Take Profit distance must be greater than zero.";
|
|
return false;
|
|
}
|
|
|
|
rr = rewardPoints / stopPoints;
|
|
rewardMoney = riskMoney * rr;
|
|
|
|
status = "Reward metrics calculated.";
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Validates entry, stop loss, and take profit structure |
|
|
//+------------------------------------------------------------------+
|
|
bool ValidateLineStructure(string &status)
|
|
{
|
|
ENUM_POSITION_TOOL_DIRECTION direction = GetSetupDirection();
|
|
|
|
if(EntryPrice == StopLossPrice)
|
|
{
|
|
status = "Invalid: Entry and Stop Loss cannot be equal.";
|
|
return false;
|
|
}
|
|
|
|
if(direction == PTD_BUY)
|
|
{
|
|
if(StopLossPrice >= EntryPrice)
|
|
{
|
|
status = "Invalid: Buy setup requires Stop Loss below Entry.";
|
|
return false;
|
|
}
|
|
|
|
if(TakeProfitPrice <= EntryPrice)
|
|
{
|
|
status = "Warning: Buy setup requires Take Profit above Entry.";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(direction == PTD_SELL)
|
|
{
|
|
if(StopLossPrice <= EntryPrice)
|
|
{
|
|
status = "Invalid: Sell setup requires Stop Loss above Entry.";
|
|
return false;
|
|
}
|
|
|
|
if(TakeProfitPrice >= EntryPrice)
|
|
{
|
|
status = "Warning: Sell setup requires Take Profit below Entry.";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
status = "Valid setup.";
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Creates dashboard background panel |
|
|
//+------------------------------------------------------------------+
|
|
void CreateDashboardBackground()
|
|
{
|
|
ObjectDelete(0,PANEL_BG_NAME);
|
|
|
|
if(!ObjectCreate(0,PANEL_BG_NAME,OBJ_RECTANGLE_LABEL,0,0,0))
|
|
return;
|
|
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_CORNER,CORNER_LEFT_UPPER);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_XDISTANCE,PANEL_X - 10);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_YDISTANCE,PANEL_Y - 10);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_XSIZE,PANEL_WIDTH);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_YSIZE,PANEL_HEIGHT);
|
|
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_BGCOLOR,clrBlack);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_COLOR,clrDimGray);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_BORDER_TYPE,BORDER_FLAT);
|
|
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_BACK,false);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_ZORDER,100);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_SELECTABLE,false);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_SELECTED,false);
|
|
ObjectSetInteger(0,PANEL_BG_NAME,OBJPROP_HIDDEN,true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Creates or updates a dashboard label |
|
|
//+------------------------------------------------------------------+
|
|
void SetPanelText(string name,string text,int x,int y,color textColor)
|
|
{
|
|
if(ObjectFind(0,name) < 0)
|
|
{
|
|
if(!ObjectCreate(0,name,OBJ_LABEL,0,0,0))
|
|
return;
|
|
|
|
ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
|
|
ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
|
|
ObjectSetInteger(0,name,OBJPROP_FONTSIZE,9);
|
|
ObjectSetString(0,name,OBJPROP_FONT,"Tahoma");
|
|
|
|
ObjectSetInteger(0,name,OBJPROP_BACK,false);
|
|
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
|
|
ObjectSetInteger(0,name,OBJPROP_SELECTED,false);
|
|
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
|
|
ObjectSetInteger(0,name,OBJPROP_ZORDER,101);
|
|
}
|
|
|
|
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
|
|
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
|
|
ObjectSetInteger(0,name,OBJPROP_COLOR,textColor);
|
|
ObjectSetString(0,name,OBJPROP_TEXT,text);
|
|
}
|
|
|
|
void CreateDashboard()
|
|
{
|
|
CreateDashboardBackground();
|
|
|
|
for(int i = 0; i < 15; i++)
|
|
{
|
|
string name = PANEL_PREFIX + IntegerToString(i);
|
|
SetPanelText(name,"",PANEL_X,PANEL_Y + i * PANEL_LINE_GAP,PANEL_TEXT);
|
|
}
|
|
|
|
ChartRedraw(0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns selected order type text |
|
|
//+------------------------------------------------------------------+
|
|
string GetOrderTypeText()
|
|
{
|
|
switch(InpOrderType)
|
|
{
|
|
case PTO_BUY_MARKET:
|
|
return "Buy Market";
|
|
|
|
case PTO_SELL_MARKET:
|
|
return "Sell Market";
|
|
|
|
case PTO_BUY_LIMIT:
|
|
return "Buy Limit";
|
|
|
|
case PTO_SELL_LIMIT:
|
|
return "Sell Limit";
|
|
|
|
case PTO_BUY_STOP:
|
|
return "Buy Stop";
|
|
|
|
case PTO_SELL_STOP:
|
|
return "Sell Stop";
|
|
}
|
|
|
|
return "Unknown";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Updates dashboard values |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateDashboard()
|
|
{
|
|
UpdateLinePrices();
|
|
|
|
string status = "";
|
|
|
|
double stopDistance = 0.0;
|
|
double stopPoints = 0.0;
|
|
double riskMoney = 0.0;
|
|
double lotSize = 0.0;
|
|
double rewardPoints = 0.0;
|
|
double rr = 0.0;
|
|
double rewardMoney = 0.0;
|
|
|
|
bool valid = ValidateLineStructure(status);
|
|
|
|
if(valid)
|
|
valid = CalculateStopLossDistance(stopDistance,stopPoints,status);
|
|
|
|
if(valid)
|
|
{
|
|
riskMoney = CalculateRiskAmount();
|
|
valid = CalculateLotSize(stopDistance,riskMoney,lotSize,status);
|
|
}
|
|
|
|
if(valid)
|
|
valid = CalculateRewardMetrics(stopPoints,riskMoney,rewardPoints,rr,rewardMoney,status);
|
|
|
|
SetPanelText(PANEL_PREFIX + "0","Position Size Tool",PANEL_X,PANEL_Y + 0 * PANEL_LINE_GAP,PANEL_TITLE);
|
|
SetPanelText(PANEL_PREFIX + "1","Symbol: " + _Symbol,PANEL_X,PANEL_Y + 1 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "2","Order Type: " + GetOrderTypeText(),PANEL_X,PANEL_Y + 2 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "3","Direction: " + GetDirectionText(),PANEL_X,PANEL_Y + 3 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
|
|
SetPanelText(PANEL_PREFIX + "4","Entry: " + DoubleToString(EntryPrice,_Digits),PANEL_X,PANEL_Y + 4 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "5","Stop Loss: " + DoubleToString(StopLossPrice,_Digits),PANEL_X,PANEL_Y + 5 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "6","Take Profit: " + DoubleToString(TakeProfitPrice,_Digits),PANEL_X,PANEL_Y + 6 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
|
|
SetPanelText(PANEL_PREFIX + "7","SL Points: " + DoubleToString(stopPoints,1),PANEL_X,PANEL_Y + 7 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "8","TP Points: " + DoubleToString(rewardPoints,1),PANEL_X,PANEL_Y + 8 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
|
|
SetPanelText(PANEL_PREFIX + "9","Risk: " + DoubleToString(InpRiskPercent,2) + "%",PANEL_X,PANEL_Y + 9 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "10","Risk Money: " + DoubleToString(riskMoney,2),PANEL_X,PANEL_Y + 10 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "11","Reward Money: " + DoubleToString(rewardMoney,2),PANEL_X,PANEL_Y + 11 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "12","Lot Size: " + DoubleToString(lotSize,2),PANEL_X,PANEL_Y + 12 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
SetPanelText(PANEL_PREFIX + "13","RR: 1:" + DoubleToString(rr,2),PANEL_X,PANEL_Y + 13 * PANEL_LINE_GAP,PANEL_TEXT);
|
|
|
|
SetPanelText(PANEL_PREFIX + "14","Status: " + status,PANEL_X,PANEL_Y + 14 * PANEL_LINE_GAP,valid ? clrLimeGreen : clrTomato);
|
|
|
|
ChartRedraw(0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Deletes dashboard objects |
|
|
//+------------------------------------------------------------------+
|
|
void DeleteDashboard()
|
|
{
|
|
ObjectDelete(0,PANEL_BG_NAME);
|
|
|
|
for(int i = 0; i < 15; i++)
|
|
{
|
|
string name = PANEL_PREFIX + IntegerToString(i);
|
|
ObjectDelete(0,name);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Deletes position lines |
|
|
//+------------------------------------------------------------------+
|
|
void DeletePositionLines()
|
|
{
|
|
ObjectDelete(0,ENTRY_LINE_NAME);
|
|
ObjectDelete(0,SL_LINE_NAME);
|
|
ObjectDelete(0,TP_LINE_NAME);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Returns current ATR value |
|
|
//+------------------------------------------------------------------+
|
|
double GetATRValue()
|
|
{
|
|
int handle = iATR(_Symbol,InpATRTimeframe,InpATRPeriod);
|
|
|
|
if(handle == INVALID_HANDLE)
|
|
return 0.0;
|
|
|
|
double buffer[];
|
|
|
|
if(CopyBuffer(handle,0,0,1,buffer) < 1)
|
|
{
|
|
IndicatorRelease(handle);
|
|
return 0.0;
|
|
}
|
|
|
|
IndicatorRelease(handle);
|
|
|
|
return buffer[0];
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Checks whether selected order type is market execution |
|
|
//+------------------------------------------------------------------+
|
|
bool IsMarketOrderType()
|
|
{
|
|
return InpOrderType == PTO_BUY_MARKET ||
|
|
InpOrderType == PTO_SELL_MARKET;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Updates market order entry line from Bid/Ask |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateMarketEntryPrice()
|
|
{
|
|
if(!IsMarketOrderType())
|
|
return;
|
|
|
|
if(InpOrderType == PTO_BUY_MARKET)
|
|
EntryPrice = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
|
|
else if(InpOrderType == PTO_SELL_MARKET)
|
|
EntryPrice = SymbolInfoDouble(_Symbol,SYMBOL_BID);
|
|
|
|
ObjectMove(0,ENTRY_LINE_NAME,0,0,EntryPrice);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Configures chart display settings |
|
|
//+------------------------------------------------------------------+
|
|
void ConfigureChartDisplay()
|
|
{
|
|
ChartSetInteger(0,CHART_SHOW_ASK_LINE,false);
|
|
ChartSetInteger(0,CHART_SHOW_BID_LINE,false);
|
|
ChartSetInteger(0,CHART_FOREGROUND,false);
|
|
ChartSetInteger(0,CHART_SHOW_OBJECT_DESCR,true);
|
|
|
|
ChartRedraw(0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Applies Position Size Tool chart appearance |
|
|
//+------------------------------------------------------------------+
|
|
void ConfigureChartAppearance()
|
|
{
|
|
ChartSetInteger(0,CHART_COLOR_BACKGROUND,clrWhite);
|
|
|
|
ChartSetInteger(0,CHART_SHOW_GRID,false);
|
|
|
|
ChartSetInteger(0,CHART_MODE,CHART_CANDLES);
|
|
|
|
ChartSetInteger(0,CHART_COLOR_FOREGROUND,clrBlack);
|
|
|
|
ChartSetInteger(0,CHART_COLOR_CANDLE_BULL,clrLimeGreen);
|
|
ChartSetInteger(0,CHART_COLOR_CANDLE_BEAR,clrTomato);
|
|
|
|
ChartSetInteger(0,CHART_COLOR_CHART_UP,clrLimeGreen);
|
|
ChartSetInteger(0,CHART_COLOR_CHART_DOWN,clrTomato);
|
|
|
|
ChartSetInteger(0,CHART_COLOR_BID,clrDodgerBlue);
|
|
ChartSetInteger(0,CHART_COLOR_ASK,clrOrange);
|
|
|
|
ChartSetInteger(0,CHART_SHOW_ASK_LINE,false);
|
|
ChartSetInteger(0,CHART_SHOW_BID_LINE,false);
|
|
|
|
ChartRedraw(0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|