Price Data Components
Orders Execution
Indicators Used
Miscellaneous
0
Views
0
Downloads
0
Favorites
Buy Stop Bracket
//+------------------------------------------------------------------+
//| Buy Limit Bracket.mq4 |
//| Copyright 2020, Niclas Hummel Trading |
//| https://niclashummel.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Niclas Hummel Trading"
#property link "https://niclashummel.com/"
#property version "1.21"
#property strict
#property show_inputs
#define INDEX uint // Zero based.
#define COUNT uint // One based.
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum enum_SwitchOnOff
{
ON=1,OFF=0
};
double res1[];
double res2[][1000];
double corr[];
string currencies[];
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
input double StDMultiplier = 1.0; // Stop Multiplier (1.0 = unchanged)
input double LotMultiplier = 1.0; // Lotsize Multiplier
input double TargetMultiplier = 2.0; // Risk to Reward Multiplier (1:x Target)
input int stDPeriod = 30; // Standard Deviation Period for Stoploss
input int lookBack = 90; // Lookback Period for Correlation Coefficient
input enum_SwitchOnOff RiskPercentage = ON; // Risk In Percentage ON/OFF
input double RiskPercent = 5.0; // Riskpercentage of Accountbalance
input double RiskAmount = 50.00; // Riskamount if Riskpercentage OFF
input int MagicNumber = 213891; // Magic Number
double riskInCurr = 0.0;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
//--- resize Array to number of lookback period
ArrayResize(res1,lookBack);
//--- execute long order
_longOrder();
}
//+------------------------------------------------------------------+
void _longOrder()
{
//--- prepare variables for OrderSend()
double stD = iStdDev(NULL,0,stDPeriod,0,MODE_SMMA,PRICE_CLOSE,1) * StDMultiplier;
double stD2 = iStdDev(NULL,0,stDPeriod,0,MODE_SMMA,PRICE_CLOSE,1);
double StopBPS = stD/Close[1];
double stoplevel = MarketInfo(NULL,MODE_STOPLEVEL)*Point;
double ask = MarketInfo(NULL,MODE_ASK);
double tv = MarketInfo(NULL,MODE_TICKVALUE);
double ts = MarketInfo(NULL,MODE_TICKSIZE);
riskInCurr = RiskPercentage ? ((RiskPercent/100)*AccountBalance()) : RiskAmount;
double _lotSize=NormalizeDouble(riskInCurr/(ask*StopBPS*(tv/ts)),(int)MarketInfo(NULL,MODE_DIGITS));
//--- check for minimum and maximum lot size
if(_lotSize < SymbolInfoDouble(NULL,SYMBOL_VOLUME_MIN))
_lotSize = SymbolInfoDouble(NULL,SYMBOL_VOLUME_MIN);
if(_lotSize > SymbolInfoDouble(NULL,SYMBOL_VOLUME_MAX))
_lotSize = SymbolInfoDouble(NULL,SYMBOL_VOLUME_MAX);
//--- _lotSize gets multiplied by correlation coefficients
_lotSize *= calcCCs();
//--- _lotSize gets adjusted to Lotstep
_lotSize = NormalizeDouble(MathFloor(_lotSize / MarketInfo(NULL,MODE_LOTSTEP)) * MarketInfo(NULL,MODE_LOTSTEP) * LotMultiplier,2);
if(_lotSize == 0)
{
Alert("Lotsize can't be applied, because Minimum Lotsize risk goes over risk threshold. Reduce risk threshold and start again");
ExpertRemove();
}
if(CheckMoneyForTrade(_lotSize,OP_BUYSTOP))
{
Print("komm wa hier rein???");
if(!OrderSend(NULL,OP_BUYSTOP,_lotSize,NormalizeDouble(ask+stD2,Digits),2,
NormalizeDouble(ask+stD2-stD,Digits),
NormalizeDouble(ask+stD2+stD*TargetMultiplier,Digits),(string)stD,MagicNumber))
GetLastError();
}
}
//+------------------------------------------------------------------+
//| Checks if enough margin is available for opening the trade |
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(double lots,int type)
{
if(lots < 0) {
Alert("Can't open trade because correlations are too high or position size can't be adjusted");
return false;
}
if(type%2==0)
type=0;
else
type = 1;
double free_margin=AccountFreeMarginCheck(Symbol(),type,lots);
//-- if not enough money
if(free_margin<0)
{
Alert("Not enough money for " + (string)lots + " Lots in " + (string)Symbol() + " Error code = " + (string)GetLastError());
return false;
}
//-- check successfull
return true;
}
//+------------------------------------------------------------------+
//| Calculates correlation coefficients and takes into account, that |
//| there can be different initial stoplosses, that affect the |
//| consideration weight of the correlation coefficient |
//+------------------------------------------------------------------+
double calcCCs()
{
//--- first create a series and fill res1 with current symbol for looking back lookBack period (=90)
createSeriesThisSymbol();
int count = 0;
//--- go through all orders
for(int j = 0; j < OrdersTotal(); j++)
{
if(!OrderSelect(j,SELECT_BY_POS,MODE_TRADES))
GetLastError();
//--- only if it's not the same symbol, that the trade is made and if not already targeted
if(OrderCloseTime() == 0 && OrderSymbol() != Symbol() && !isInCurrencyList(OrderSymbol()))
{
//--- resize res2 to amount of runs
ArrayResize(res2,count+1);
//--- fill res2, depending on the currency with close to close % returns
for(int i = 0; i < lookBack; i++)
{
string Symbol2 = OrderSymbol();
res2[count][i] = (iClose(Symbol2,0,i)-iClose(Symbol2,0,i+1))/iClose(Symbol2,0,i);
}
//--- resize currencies to amount of runs
ArrayResize(currencies,count+1);
//--- fill currencies to identifier = amount of runs (= amount of other currencies/symbols with open orders)
currencies[count] = OrderSymbol();
count++;
}
}
int l = 0;
int sizeRes2 = (int)ArraySize(res2)/1000;
//--- go through all symbols with open orders
for(int k = 0; k < sizeRes2; k++)
{
//--- calculate correlation coefficient
double cc = MathAbs(correlation_coefficient(res1,res2,k,lookBack));
if(cc >= 0.1)
{
ArrayResize(corr,l+1);
//--- save correlation coefficient in corr array
corr[l] = cc;
l++;
}
}
double correlation_decrease_factor = 1.0;
if(ArraySize(corr) >= 1)
{
//--- sort for highest correlation coefficient
ArraySort(corr);
for(int o = ArraySize(corr)-1; o >= 0; o--)
{
//--- calculate the amount that the position size should be reduced
//--- takes into account the riskRatio = relation to initial full position size
correlation_decrease_factor *= (1-corr[o]*riskRatio(currencies[o]));
}
}
return correlation_decrease_factor;
}
//+------------------------------------------------------------------+
//| This function calculates the ratio between the full currency |
//| amount and the already invested initial risk in currency of the |
//| open positions |
//+------------------------------------------------------------------+
double riskRatio(string OS)
{
return ((totalLots(OS) * stoploss_distance(OS) * MarketInfo(OS,MODE_TICKVALUE)) / MarketInfo(OS,MODE_TICKSIZE)) / riskInCurr;
}
//+------------------------------------------------------------------+
//| Creates a series of close to close % returns |
//+------------------------------------------------------------------+
void createSeriesThisSymbol()
{
for(int i = 0; i < lookBack; i++)
{
res1[i] = (Close[i]-Close[i+1])/Close[i];
}
}
//+------------------------------------------------------------------+
//| Calculates correlation coefficient of two arrays |
//+------------------------------------------------------------------+
double correlation_coefficient(double& a[], double& b[][], int k, COUNT length, INDEX iBeg=0)
{
INDEX iEnd = iBeg + length;
double Ex=0.0, Ex2=0.0, Ey=0.0, Ey2=0.0, Exy=0.0; // Ex=Sum(x)
for(; iBeg < iEnd; ++iBeg)
{
double x = a[iBeg], y = b[k][iBeg];
Ex += x;
Ex2 += x * x;
Ey += y;
Ey2 += y * y;
Exy += x * y;
}
double ssxy = length * Exy - Ex * Ey;
double ssxx = length * Ex2 - Ex * Ex;
double ssyy = length * Ey2 - Ey * Ey;
double deno = MathSqrt(ssxx * ssyy);
return (deno == 0.0) ? 0.0 : ssxy / deno;
}
//+------------------------------------------------------------------+
//| Checks if the OrderSymbol os in the argument is in the currencies|
//| array |
//+------------------------------------------------------------------+
bool isInCurrencyList(string os)
{
for(int i = 0; i < ArraySize(currencies); i++)
{
if(os == currencies[i])
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Calculates the stoploss distance between the initial stoploss |
//| and the current average price |
//+------------------------------------------------------------------+
double stoploss_distance(string OS)
{
double avge=1, avge_sl = 1, Avgprice=0, Avgprice_sl=0, lts=0;
//--- saves open buy and sell orders in count variables
int longcount = countOrders(OP_BUY,OS);
int shortcount = countOrders(OP_SELL,OS);
if(longcount == 0 && shortcount == 0)
{
longcount = 1;
shortcount = 1;
}
string ordercomment = "";
//--- finds the ordercomment with the initial stoploss (when opened by my script with MagicNumber)
for(int i = 0; i<=OrdersTotal(); i++)
{
if(!OrderSelect(i,SELECT_BY_POS))
GetLastError();
if(OrderType() < 2 && OrderSymbol() == OS && OrderMagicNumber() == MagicNumber)
{
ordercomment = OrderComment();
break;
}
}
//--- if more long orders
if(longcount > shortcount)
{
//--- first calculate total Lots
for(int i = 0; i<=OrdersTotal(); i++)
{
if(!OrderSelect(i,SELECT_BY_POS))
GetLastError();
if(OrderType() == OP_BUY && OrderSymbol() == OS)
{
lts+= OrderLots();
}
}
//--- then calculate the average entry price and stoploss
for(int h = 0; h<=OrdersTotal(); h++)
{
if(!OrderSelect(h,SELECT_BY_POS))
GetLastError();
if(OrderType() == OP_BUY && OrderSymbol() == OS)
{
Avgprice+= OrderOpenPrice() * (OrderLots() / lts);
Avgprice_sl+= OrderStopLoss() * (OrderLots() / lts);
}
}
avge = NormalizeDouble(Avgprice,(int)MarketInfo(OS,MODE_DIGITS));
avge_sl = NormalizeDouble(Avgprice_sl,(int)MarketInfo(OS,MODE_DIGITS));
}
//--- if more short orders
else
{
//--- first calculate total Lots
for(int u = 0; u<=OrdersTotal(); u++)
{
if(!OrderSelect(u,SELECT_BY_POS))
GetLastError();
if(OrderType() == OP_SELL && OrderSymbol() == OS)
{
lts+= OrderLots();
}
}
//--- then calculate the average entry price and stoploss
for(int j = 0; j<=OrdersTotal(); j++)
{
if(!OrderSelect(j,SELECT_BY_POS))
GetLastError();
if(OrderType() == OP_SELL && OrderSymbol() == OS)
{
Avgprice+= OrderOpenPrice() * (OrderLots() / lts);
Avgprice_sl+= OrderStopLoss() * (OrderLots() / lts);
}
}
avge = NormalizeDouble(Avgprice,(int)MarketInfo(OS,MODE_DIGITS));
avge_sl = NormalizeDouble(Avgprice_sl,(int)MarketInfo(OS,MODE_DIGITS));
}
if(avge == 1)
avge = 0.0;
if(avge_sl == 1)
avge_sl = 0.0;
double oc = (double)ordercomment;
//--- if no order was opened there's no initial stoploss, so take the average stoploss
if(oc == 0)
{
return MathAbs(avge_sl-avge);
} else {
return oc;
}
}
//+------------------------------------------------------------------+
//| Counts all orders with certain OrderType in certain Symbol |
//+------------------------------------------------------------------+
int countOrders(int oType,string OS)
{
int count=0;
for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS))
{
if(OrderSymbol()==OS)
{
if(OrderType()==oType || oType<0)
{
count++;
}
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| Returns total Lots for certain Symbol of open orders |
//+------------------------------------------------------------------+
double totalLots(string OS)
{
double lts = 0.0;
for(int i = 0; i<=OrdersTotal(); i++)
{
if(!OrderSelect(i,SELECT_BY_POS))
GetLastError();
if(OrderType() < 2 && OrderSymbol() == OS)
{
lts+= OrderLots();
}
}
return lts;
}
//+------------------------------------------------------------------+
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---