sonic/sonic.mq5
super.admin fda2c1c26a convert
2025-05-30 16:25:19 +02:00

440 lines
16 KiB
MQL5

//+------------------------------------------------------------------+
//| sonic |
//| Copyright 2021, NhatNamBe |
//| |
//+------------------------------------------------------------------+
#include "init.mqh"
#include "pnlInfo.mqh"
input int MagicNumber=1234567; // Expert Advisor ID
input bool DescriptionModeFull=true; // Detailed output mode
input double inputProfit=0.00005; // Profit
input double step=0.00005; // Step
input double amount=0.01; // Amount
input double reachPNL=0.001; // Reach PNL
input int maxOrder=5; // Max Order
input string testSide="Buy"; // Side for backtest
datetime history_start;
ulong currentPendingBuyTicket=0;
ulong currentPendingSellTicket=0;
bool tradingLong=false;
bool tradingShort=false;
CpnlInfo ExtScript;
//+------------------------------------------------------------------+
//|Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- check if autotrading is allowed
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Alert("Autotrading in the terminal is disabled, Expert Advisor will be removed.");
ExpertRemove();
return(-1);
}
int ret=CheckAccount();
if(ret)
{
ExpertRemove();
return(ret);
}
GetSymbolInfo();
//--- save the time of launching the Expert Advisor for receiving trading history
history_start=TimeCurrent();
//---
if(MQLInfoInteger(MQL_TESTER))
{
Print("Backtest");
if(testSide=="Buy")
{
tradingLong=true;
CheckPositionAndPlaceNewTrade(POSITION_TYPE_BUY);
}
else
if(testSide=="Sell")
{
tradingShort=true;
CheckPositionAndPlaceNewTrade(POSITION_TYPE_SELL);
}
}
else
CreateBuySellButtons();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- delete all graphical objects
ObjectDelete(0,"Buy");
ObjectDelete(0,"Sell");
EventKillTimer();
//---
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTimer()
{
PNLStart();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void PNLStart()
{
double pPnl = ExtScript.Processing(0.001);
if(pPnl)
{
// TODO: Do something here
closePosition();
ExtScript.SetLastPnl(pPnl);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void closePosition()
{
// TODO:
// 1. cancel all open-order
// 2. closed trade
ENUM_POSITION_TYPE targetType = POSITION_TYPE_BUY;
CPositionInfo position;
double nearestTakeProfit=0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket>0)
{
position.SelectByTicket(ticket);
ENUM_POSITION_TYPE posType = position.PositionType();
double tpPrice = position.TakeProfit();
Print(EnumToString(posType) + " : " + (string)ticket + " price: " + tpPrice);
CTrade trade;
//trade.PositionClose(_Symbol);
if(!trade.PositionClose(ticket))
{
Print("Loi roi....");
}
}
}
while(true)
{
int i = PositionsTotal() - 1;
if(i <= 0)
{
break;
}
Sleep(1000);
}
}
//+------------------------------------------------------------------+
//| TradeTransaction function |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
ulong lastOrderID =trans.order;
ENUM_ORDER_TYPE lastOrderType =trans.order_type;
ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- the name of the symbol, for which a transaction was performed
string trans_symbol=trans.symbol;
//--- type of transaction
ENUM_TRADE_TRANSACTION_TYPE trans_type=trans.type;
switch(trans.type)
{
case TRADE_TRANSACTION_HISTORY_ADD: // adding an order to the history
{
//--- order ID in an external system - a ticket assigned by an Exchange
string Exchange_ticket="";
if(lastOrderState==ORDER_STATE_FILLED)
{
if(HistoryOrderSelect(lastOrderID))
Exchange_ticket=HistoryOrderGetString(lastOrderID,ORDER_EXTERNAL_ID);
if(Exchange_ticket!="")
Exchange_ticket=StringFormat("(Exchange ticket=%s)",Exchange_ticket);
}
PrintFormat("MqlTradeTransaction: %s order #%d %s %s %s %s",EnumToString(trans_type),
lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
if(lastOrderState==ORDER_STATE_FILLED)
{
ENUM_POSITION_TYPE targetType;
if(lastOrderID==currentPendingBuyTicket)
currentPendingBuyTicket=0;
else
if(lastOrderID==currentPendingSellTicket)
currentPendingSellTicket=0;
}
}
break;
default: // other transactions
{
}
break;
}
//---
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTrade(void)
{
static int positions=0; // number of open positions
int curr_positions=PositionsTotal();
if(curr_positions!=positions)
{
positions=curr_positions;
if(tradingLong)
CheckPositionAndPlaceNewTrade(POSITION_TYPE_BUY);
if(tradingShort)
CheckPositionAndPlaceNewTrade(POSITION_TYPE_SELL);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CheckPositionAndPlaceNewTrade(ENUM_POSITION_TYPE targetType)
{
if((targetType==POSITION_TYPE_BUY && !tradingLong) || (targetType==POSITION_TYPE_SELL && !tradingShort))
{
Print("### " + EnumToString(targetType) + " is disable");
return;
}
CPositionInfo position;
CTrade trade;
COrderInfo orderInfo;
double nearestPos=0;
double farthestPos=0;
ulong farthestTicket=0;
ulong currentPendingTicket;
int openPosNum=0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket>0)
{
position.SelectByTicket(ticket);
ENUM_POSITION_TYPE posType = position.PositionType();
double posPrice = position.PriceOpen();
//Print(EnumToString(posType) + " : " + (string)ticket + " price: " + tpPrice);
if(targetType==posType)
{
if(!nearestPos || nearestPos*GetStepWise(targetType) > posPrice*GetStepWise(targetType))
nearestPos=posPrice;
if(!farthestTicket || farthestPos*GetStepWise(targetType) < posPrice*GetStepWise(targetType))
{
farthestPos=posPrice;
farthestTicket=ticket;
}
}
}
}
openPosNum+=1;
if(openPosNum > maxOrder)
{
//--- Cut farthest one
Print("### Reach max order, cut farthest Pos " + farthestTicket + " at " + farthestPos);
trade.PositionClose(farthestTicket);
}
if(targetType==POSITION_TYPE_BUY)
currentPendingTicket=currentPendingBuyTicket;
else
currentPendingTicket=currentPendingSellTicket;
if(!nearestPos)
{
Print("#### " + EnumToString(targetType) + " there is no pos yet");
if(currentPendingTicket)
{
//--- delete existing pending order
trade.OrderDelete(currentPendingTicket);
}
//--- receiving a buy price
double price=(targetType==POSITION_TYPE_BUY)?SymbolInfoDouble(_Symbol,SYMBOL_ASK):SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- filling comments
ENUM_ORDER_TYPE order_type=(targetType==POSITION_TYPE_BUY)?ORDER_TYPE_BUY:ORDER_TYPE_SELL;
string comment=EnumToString(order_type) + " market "+_Symbol+" "+amount+" at "+ price;
Print(comment);
//--- everything is ready, trying to open a buy position
currentPendingTicket=PlaceOrder(_Symbol, targetType, order_type, amount, price, 0, inputProfit, comment);
}
else
{
Print("#### " + EnumToString(targetType) + " nearestPos: " + nearestPos);
//--- receiving a buy price
double price=nearestPos - GetStepWise(targetType)*step;
//--- filling comments
ENUM_ORDER_TYPE order_type=(targetType==POSITION_TYPE_BUY)?ORDER_TYPE_BUY_LIMIT:ORDER_TYPE_SELL_LIMIT;
string comment=EnumToString(order_type) + " " +_Symbol+" "+amount+" at "+ price;
Print(comment);
//--- everything is ready, trying to open a buy position
if(currentPendingTicket)
{
//--- check if new pending order is same to existing one
orderInfo.Select(currentPendingTicket);
double existPrice=orderInfo.PriceOpen();
if(existPrice==price)
{
Print("existing price ", existPrice);
return;
}
//--- delete existing pending order
trade.OrderDelete(currentPendingTicket);
}
currentPendingTicket=PlaceOrder(_Symbol, targetType, order_type, amount, price, 0, inputProfit, comment);
}
if(targetType==POSITION_TYPE_BUY)
currentPendingBuyTicket=currentPendingTicket;
else
currentPendingSellTicket=currentPendingTicket;
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
CTrade trade;
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
if(id==CHARTEVENT_OBJECT_CLICK)
{
Print("=> ",__FUNCTION__,": sparam = ",sparam);
//--- minimum volume for a deal
// double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
//--- if "Buy" button is pressed, then buy
if(sparam=="Buy")
{
tradingLong=true;
CheckPositionAndPlaceNewTrade(POSITION_TYPE_BUY);
//--- unpress the button
ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
}
//--- if "Sell" button is pressed, then sell
if(sparam=="Sell")
{
tradingShort=true;
CheckPositionAndPlaceNewTrade(POSITION_TYPE_SELL);
//--- unpress the button
ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
}
if(sparam=="BuyStop")
{
//--- unpress the button
ObjectSetInteger(0,"BuyStop",OBJPROP_STATE,false);
if(currentPendingBuyTicket)
trade.OrderDelete(currentPendingBuyTicket);
tradingLong=false;
}
//--- if "Sell" button is pressed, then sell
if(sparam=="SellStop")
{
//--- unpress the button
ObjectSetInteger(0,"SellStop",OBJPROP_STATE,false);
if(currentPendingSellTicket)
trade.OrderDelete(currentPendingSellTicket);
tradingShort=false;
}
ChartRedraw();
}
//---
}
//+------------------------------------------------------------------+
//| Create two buttons for buying and selling |
//+------------------------------------------------------------------+
void CreateBuySellButtons()
{
//--- check the object named "Buy"
if(ObjectFind(0,"Buy")>=0)
{
//--- if the found object is not a button, delete it
if(ObjectGetInteger(0,"Buy",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"Buy");
}
else
ObjectCreate(0,"Buy",OBJ_BUTTON,0,0,0); // create "Buy" button
//--- configure "Buy" button
ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrGreen);
//--- check presence of the object named "Sell"
if(ObjectFind(0,"Sell")>=0)
{
//--- if the found object is not a button, delete it
if(ObjectGetInteger(0,"Sell",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"Sell");
}
else
ObjectCreate(0,"Sell",OBJ_BUTTON,0,0,0); // create "Sell" button
//--- configure "Sell" button
ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrRed);
//--- check the object named "BuyStop"
if(ObjectFind(0,"BuyStop")>=0)
{
//--- if the found object is not a button, delete it
if(ObjectGetInteger(0,"BuyStop",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"BuyStop");
}
else
ObjectCreate(0,"BuyStop",OBJ_BUTTON,0,0,0); // create "Buy" button
//--- configure "Buy" button
ObjectSetInteger(0,"BuyStop",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"BuyStop",OBJPROP_XDISTANCE,250);
ObjectSetInteger(0,"BuyStop",OBJPROP_YDISTANCE,50);
ObjectSetInteger(0,"BuyStop",OBJPROP_XSIZE,150);
ObjectSetInteger(0,"BuyStop",OBJPROP_YSIZE,30);
ObjectSetString(0,"BuyStop",OBJPROP_TEXT,"Pause Buy");
ObjectSetInteger(0,"BuyStop",OBJPROP_COLOR,clrGreen);
//--- check presence of the object named "SellStop"
if(ObjectFind(0,"SellStop")>=0)
{
//--- if the found object is not a button, delete it
if(ObjectGetInteger(0,"SellStop",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"SellStop");
}
else
ObjectCreate(0,"SellStop",OBJ_BUTTON,0,0,0); // create "SellStop" button
//--- configure "SellStop" button
ObjectSetInteger(0,"SellStop",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"SellStop",OBJPROP_XDISTANCE,250);
ObjectSetInteger(0,"SellStop",OBJPROP_YDISTANCE,100);
ObjectSetInteger(0,"SellStop",OBJPROP_XSIZE,150);
ObjectSetInteger(0,"SellStop",OBJPROP_YSIZE,30);
ObjectSetString(0,"SellStop",OBJPROP_TEXT,"Pause Sell");
ObjectSetInteger(0,"SellStop",OBJPROP_COLOR,clrRed);
//--- perform forced update of the chart to see the buttons immediately
ChartRedraw();
//---
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+