337 lines
No EOL
23 KiB
MQL5
337 lines
No EOL
23 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| HAL8999 Expert Advisor |
|
|
//| Vincent McFaul & Viggo Mattson |
|
|
//| Copyright © 2023 |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//can open b/s position
|
|
#include<Trade\Trade.mqh>
|
|
CTrade trade;
|
|
#include <Trade\PositionInfo.mqh>
|
|
CPositionInfo positioninfo;
|
|
|
|
//update function
|
|
void OnTick()
|
|
{
|
|
|
|
//-----------------------------------------------------------MISCELLANEOUS SYSTEMS-----------------------------------------------------------//
|
|
|
|
//get current ask, bid and balance price of open chart
|
|
double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
|
|
double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
|
|
double Balance=AccountInfoDouble(ACCOUNT_BALANCE);
|
|
double Equity=AccountInfoDouble(ACCOUNT_EQUITY);
|
|
double LiveProfit=Equity-Balance;
|
|
|
|
//fixed lotsize per 1000 currency
|
|
double LotSize;
|
|
if(Balance<2000)
|
|
{
|
|
LotSize = 0.01;
|
|
}
|
|
else
|
|
{
|
|
LotSize=(MathFloor(Balance/100))/1000;
|
|
}
|
|
|
|
//track price data for candles on open chart
|
|
MqlRates PriceInformation[];
|
|
ArraySetAsSeries(PriceInformation, true);
|
|
CopyRates(Symbol(),PERIOD_M1,0,360, PriceInformation);
|
|
|
|
//get max and min price over 100 5-min periods
|
|
double HighCandles[];
|
|
double LowCandles[];
|
|
ArraySetAsSeries(HighCandles, true);
|
|
ArraySetAsSeries(LowCandles, true);
|
|
CopyHigh(_Symbol,PERIOD_M1,0,360,HighCandles);
|
|
CopyLow(_Symbol,PERIOD_M1,0,360,LowCandles);
|
|
|
|
//15 points + 6-hour range
|
|
double ExtremumRange = ((PriceInformation[ArrayMaximum(HighCandles,0,360)].high)-(PriceInformation[ArrayMinimum(LowCandles,0,360)].low));
|
|
double DistanceToOrder = (15*_Point)+ExtremumRange;
|
|
|
|
//get price max/min
|
|
double MaxPrice= (PriceInformation[0].open)+DistanceToOrder;
|
|
double MinPrice= (PriceInformation[0].open)-DistanceToOrder;
|
|
|
|
//get best takeprofit price
|
|
double TakeProfitPriceByLotSum = 0;
|
|
double TakeProfitLotSum = 0;
|
|
|
|
if(PositionsTotal()>0)
|
|
{
|
|
for(int i=PositionsTotal()-1;i>=0;i--)
|
|
{
|
|
PositionSelectByTicket(PositionGetTicket(i));
|
|
ulong PositionTicket = PositionGetTicket(i);
|
|
double PositionPriceOpen=positioninfo.PriceOpen();
|
|
double PositionLotSize=PositionGetDouble(POSITION_VOLUME);
|
|
|
|
TakeProfitPriceByLotSum += (PositionPriceOpen*PositionLotSize);
|
|
TakeProfitLotSum += PositionLotSize;
|
|
}
|
|
}
|
|
|
|
double BuyTakeProfitPriceFinal = (TakeProfitPriceByLotSum/TakeProfitLotSum)+(200*_Point);
|
|
double SellTakeProfitPriceFinal = (TakeProfitPriceByLotSum/TakeProfitLotSum)-(200*_Point);
|
|
|
|
//-----------------------------------------------------------STOCHASTIC K INDICATOR-----------------------------------------------------------//
|
|
|
|
string SKsignal ="";
|
|
|
|
double KArray[];
|
|
|
|
//sort from current candle downwards
|
|
ArraySetAsSeries(KArray,true);
|
|
|
|
//defined STOCHASTIC-K signal
|
|
int StochasticDefinition = iStochastic(_Symbol,PERIOD_M5,9,3,3,MODE_SMA,STO_LOWHIGH);
|
|
|
|
//fill array with price data
|
|
CopyBuffer(StochasticDefinition,0,0,3,KArray);
|
|
|
|
//last calculated candle value
|
|
double KValue1=KArray[1];
|
|
|
|
//buy signal below 35
|
|
if(KValue1<35)
|
|
{
|
|
SKsignal="buy";
|
|
}
|
|
|
|
//sell signal above 65
|
|
if(KValue1>65)
|
|
{
|
|
SKsignal="sell";
|
|
}
|
|
|
|
//-----------------------------------------------------------SUPER TREND INDICATOR-----------------------------------------------------------//
|
|
|
|
string STsignal ="";
|
|
|
|
double MovingAverageArray[];
|
|
|
|
//sort from current candle downwards
|
|
ArraySetAsSeries(MovingAverageArray,true);
|
|
|
|
//defined MA signal
|
|
int MovingAverageDefinition = iMA(_Symbol, PERIOD_D1, 3, 0, MODE_SMMA, PRICE_MEDIAN);
|
|
|
|
//fill array with price data
|
|
CopyBuffer(MovingAverageDefinition,0,0,3,MovingAverageArray);
|
|
|
|
//current and last MA values
|
|
double CurrentMAValue=MovingAverageArray[0];
|
|
double PreviousMAValue=MovingAverageArray[1];
|
|
|
|
//buy signal if uptrend
|
|
if(CurrentMAValue>PreviousMAValue)
|
|
{
|
|
STsignal="uptrend";
|
|
}
|
|
|
|
//buy signal if uptrend
|
|
if(CurrentMAValue<PreviousMAValue)
|
|
{
|
|
STsignal="downtrend";
|
|
}
|
|
|
|
//else
|
|
//{
|
|
//STsignal="sideway";
|
|
//}
|
|
|
|
//-----------------------------------------------------------TRADE SYSTEM-----------------------------------------------------------//
|
|
|
|
string POsignal ="";
|
|
|
|
//bar count since last open position
|
|
datetime LastPositionTime=PositionGetInteger(POSITION_TIME);
|
|
datetime CurrentTime=TimeCurrent();
|
|
int BarsFromPositionCount=Bars(_Symbol,PERIOD_M1,LastPositionTime, CurrentTime);
|
|
|
|
//pending order for sell limit
|
|
if(SKsignal=="sell"&&STsignal=="downtrend"&&PositionsTotal()<1&&OrdersTotal()<1)
|
|
{
|
|
trade.SellLimit
|
|
(
|
|
LotSize, //lot size
|
|
MaxPrice, //price
|
|
_Symbol, //symbol
|
|
((PriceInformation[1].open)+(1500*_Point)), //SL
|
|
0, //TP
|
|
ORDER_TIME_GTC, //expiration
|
|
0, //time to expire
|
|
NULL //comment
|
|
);
|
|
POsignal = "Pending Sell";
|
|
}
|
|
|
|
//pending order for buy limit
|
|
if(SKsignal=="buy"&&STsignal=="uptrend"&&PositionsTotal()<1&&OrdersTotal()<1)
|
|
{
|
|
trade.BuyLimit
|
|
(
|
|
LotSize, //lot size
|
|
MinPrice, //price
|
|
_Symbol, //symbol
|
|
((PriceInformation[1].open)-(1500*_Point)), //SL
|
|
0, //TP
|
|
ORDER_TIME_GTC, //expiration
|
|
0, //time to expire
|
|
NULL //comment
|
|
);
|
|
POsignal = "Pending Buy";
|
|
}
|
|
|
|
//trailing order
|
|
for(int i=OrdersTotal()-1;i>=0;i--){
|
|
ulong OrderTicket = OrderGetTicket(i);
|
|
|
|
if(OrderSelect(OrderTicket)){
|
|
ENUM_ORDER_TYPE OrderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
|
double CurrentOrderPrice = OrderGetDouble(ORDER_PRICE_OPEN);
|
|
double CurrentOrderStopLoss = OrderGetDouble(ORDER_SL);
|
|
double CurrentOrderTakeProfit = OrderGetDouble(ORDER_TP);
|
|
|
|
Print(MaxPrice, " ", CurrentOrderPrice);
|
|
|
|
if(OrderType == ORDER_TYPE_SELL_LIMIT){
|
|
if(MaxPrice<CurrentOrderPrice){
|
|
trade.OrderModify(OrderTicket, MaxPrice, CurrentOrderStopLoss, CurrentOrderTakeProfit, ORDER_TIME_GTC, 0);}
|
|
}
|
|
else if(OrderType == ORDER_TYPE_BUY_LIMIT){
|
|
if(MinPrice>CurrentOrderPrice){
|
|
trade.OrderModify(OrderTicket, MinPrice, CurrentOrderStopLoss, CurrentOrderTakeProfit, ORDER_TIME_GTC, 0);}
|
|
}
|
|
}
|
|
}
|
|
|
|
//setting takeprofit on positions
|
|
if(PositionsTotal()>0)
|
|
{
|
|
for(int i=PositionsTotal()-1;i>=0;i--)
|
|
{
|
|
PositionSelectByTicket(PositionGetTicket(i));
|
|
ulong PositionTicket = PositionGetTicket(i);
|
|
ENUM_POSITION_TYPE PositionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
double CurrentPositionStopLoss = PositionGetDouble(POSITION_SL);
|
|
|
|
if(PositionType == POSITION_TYPE_SELL)
|
|
{
|
|
trade.PositionModify(PositionTicket, CurrentPositionStopLoss, SellTakeProfitPriceFinal);
|
|
}
|
|
if(PositionType == POSITION_TYPE_BUY)
|
|
{
|
|
trade.PositionModify(PositionTicket, CurrentPositionStopLoss, BuyTakeProfitPriceFinal);
|
|
}
|
|
}
|
|
}
|
|
|
|
//martingale iteration
|
|
int MartinCount = PositionsTotal() - 1;
|
|
|
|
if(PositionsTotal()>0)
|
|
{
|
|
PositionSelectByTicket(PositionGetTicket(0));
|
|
ENUM_POSITION_TYPE PositionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
double CurrentPositionStopLoss = PositionGetDouble(POSITION_SL);
|
|
|
|
if(LiveProfit<(-2.0) && MartinCount==0)
|
|
{
|
|
if(PositionType == POSITION_TYPE_SELL)
|
|
{
|
|
trade.Sell((LotSize*2),_Symbol,NULL,CurrentPositionStopLoss,SellTakeProfitPriceFinal);
|
|
}
|
|
if(PositionType == POSITION_TYPE_BUY)
|
|
{
|
|
trade.Buy((LotSize*2),_Symbol,NULL,CurrentPositionStopLoss,BuyTakeProfitPriceFinal);
|
|
}
|
|
}
|
|
|
|
if(LiveProfit<(-5.0) && MartinCount==1)
|
|
{
|
|
if(PositionType == POSITION_TYPE_SELL)
|
|
{
|
|
trade.Sell((LotSize*3),_Symbol,NULL,CurrentPositionStopLoss,SellTakeProfitPriceFinal);
|
|
}
|
|
if(PositionType == POSITION_TYPE_BUY)
|
|
{
|
|
trade.Buy((LotSize*3),_Symbol,NULL,CurrentPositionStopLoss,BuyTakeProfitPriceFinal);
|
|
}
|
|
}
|
|
|
|
if(LiveProfit<(-10.0) && MartinCount==2)
|
|
{
|
|
if(PositionType == POSITION_TYPE_SELL)
|
|
{
|
|
trade.Sell((LotSize*4),_Symbol,NULL,CurrentPositionStopLoss,SellTakeProfitPriceFinal);
|
|
}
|
|
if(PositionType == POSITION_TYPE_BUY)
|
|
{
|
|
trade.Buy((LotSize*4),_Symbol,NULL,CurrentPositionStopLoss,BuyTakeProfitPriceFinal);
|
|
}
|
|
}
|
|
|
|
if(LiveProfit<(-17.0) && MartinCount==3)
|
|
{
|
|
if(PositionType == POSITION_TYPE_SELL)
|
|
{
|
|
trade.Sell((LotSize*5),_Symbol,NULL,CurrentPositionStopLoss,SellTakeProfitPriceFinal);
|
|
}
|
|
if(PositionType == POSITION_TYPE_BUY)
|
|
{
|
|
trade.Buy((LotSize*5),_Symbol,NULL,CurrentPositionStopLoss,BuyTakeProfitPriceFinal);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//close on breakeven recovery
|
|
if(PositionsTotal()>0)
|
|
{
|
|
for(int i=PositionsTotal()-1;i>=0;i--)
|
|
{
|
|
PositionSelectByTicket(PositionGetTicket(i));
|
|
ulong PositionTicket = PositionGetTicket(i);
|
|
ENUM_POSITION_TYPE PositionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
double CurrentPositionStopLoss = PositionGetDouble(POSITION_SL);
|
|
|
|
if(PositionType == POSITION_TYPE_SELL)
|
|
{
|
|
if((PriceInformation[1].close < Bid) && (LiveProfit < 0.7 && LiveProfit > 0) && (BarsFromPositionCount > 15))
|
|
{
|
|
trade.PositionClose(PositionTicket);
|
|
}
|
|
}
|
|
|
|
if(PositionType == POSITION_TYPE_BUY)
|
|
{
|
|
if((PriceInformation[1].close > Bid) && (LiveProfit < 0.7 && LiveProfit > 0) && (BarsFromPositionCount > 15))
|
|
{
|
|
trade.PositionClose(PositionTicket);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//cancel order by signal or market
|
|
for(int i=OrdersTotal()-1;i>=0;i--){
|
|
ulong OrderTicket = OrderGetTicket(i);
|
|
ENUM_ORDER_TYPE OrderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
|
|
|
if(OrderType == ORDER_TYPE_BUY_LIMIT&&SKsignal=="sell")
|
|
{
|
|
trade.OrderDelete(OrderTicket);
|
|
}
|
|
|
|
if(OrderType == ORDER_TYPE_SELL_LIMIT&&SKsignal=="buy")
|
|
{
|
|
trade.OrderDelete(OrderTicket);
|
|
}
|
|
}
|
|
|
|
Comment("SK: ", SKsignal, " / ", "ST: ", STsignal);
|
|
|
|
} |