1223 lines
No EOL
80 KiB
MQL4
1223 lines
No EOL
80 KiB
MQL4
//+------------------------------------------------------------------+
|
|
//| trendmeEA.mq4 |
|
|
//| Copyright 2019, MetaQuotes Software Corp. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#define pdxversion "1.00"
|
|
#property copyright "Klymenko Roman (needtome@icloud.com)"
|
|
#property link "https://www.mql5.com/en/users/needtome"
|
|
#property version pdxversion
|
|
#property strict
|
|
|
|
enum TypeOfPos
|
|
{
|
|
MY_BUY,
|
|
MY_SELL,
|
|
MY_BUYSTOP,
|
|
MY_BUYLIMIT,
|
|
MY_SELLSTOP,
|
|
MY_SELLLIMIT,
|
|
MY_BUYSLTP,
|
|
MY_SELLSLTP,
|
|
MY_ALLPOS,
|
|
};
|
|
enum TypeOfLang{
|
|
MY_ENG, // English
|
|
MY_RUS, // Русский
|
|
};
|
|
enum TypeOfLots //Lots Mode
|
|
{
|
|
MY_FIXED,//Fixed
|
|
MY_ARIFMET,// Arifmet
|
|
MY_GEOMET,// Geomet
|
|
};
|
|
enum TypeOfSeries //Series Mode
|
|
{
|
|
MY_SERIES_PLUS,// Following the series
|
|
MY_SERIES_MINUS,// Against the series
|
|
};
|
|
|
|
input int EA_Magic=345;
|
|
input string my_cmt="giderKatEA"; // Comment
|
|
input double Lot=0.01; // Lot size
|
|
input TypeOfLots typeLot=MY_GEOMET; // Increasing a lot in a chain
|
|
input int gridStep=30; // Grid size in points
|
|
input uint gridStepCount=0; // Steps in chain
|
|
input bool noGLong=false; // Do not open Long
|
|
input bool noGShort=false; // Do not open Short
|
|
|
|
sinput string delimeter_02=""; // --- Closing all positions
|
|
input double takeProfit=0; // Profit, $
|
|
input double takeProfit1step=0; // Profit at step 1, $
|
|
input double takeProfit2step=0; // Profit at step 2, $
|
|
input double takeProfit4step=0; // Profit at step 4, $
|
|
input double takeProfit5step=0; // Profit at step 5, $
|
|
input double takeProfit6step=0; // Profit at step 6, $
|
|
input double takeProfit7step=0; // Profit at step 7, $
|
|
input double takeProfit8step=0; // Profit at step 8, $
|
|
input double takeProfit9step=0; // Profit at step 9, $
|
|
input double equityLess=0; // If equity decreased, $
|
|
input uint gridStepCountClose=0; // Close all at trade number
|
|
sinput string delimeter_07=""; // --- In bar direction
|
|
input bool BARS_enabled=false; // Use entry by bar only
|
|
input ENUM_TIMEFRAMES BARS_Timeframe=PERIOD_D1; // Timeframe
|
|
sinput string delimeter_08=""; // --- Bar series
|
|
input int SERIES_count=0; // Enter if N bars in one direction
|
|
input TypeOfSeries SERIES_type=MY_SERIES_PLUS; // Entry direction
|
|
input ENUM_TIMEFRAMES SERIES_Timeframe=PERIOD_M15; // Timeframe
|
|
sinput string delimeter_09=""; // --- MA
|
|
input ENUM_TIMEFRAMES MA_Timeframe=PERIOD_D1; // Timeframe
|
|
input int MA_PERIOD=0; // Period
|
|
sinput string delimeter_12=""; // --- Other
|
|
input TypeOfLang LANG=MY_RUS; // Language
|
|
|
|
#ifdef __MQL5__
|
|
#include <Trade\Trade.mqh>
|
|
CTrade Trade;
|
|
|
|
enum TypeOfFilling // Filling Mode
|
|
{
|
|
FOK,//ORDER_FILLING_FOK
|
|
RETURN,// ORDER_FILLING_RETURN
|
|
IOC,//ORDER_FILLING_IOC
|
|
};
|
|
input TypeOfFilling useORDER_FILLING_RETURN=FOK; // Order filling mode
|
|
#endif
|
|
|
|
|
|
MqlTick lastme;
|
|
uint LongPos=0;
|
|
uint ShortPos=0;
|
|
double LongVol=0;
|
|
double ShortVol=0;
|
|
string prefix_graph="griderKat_";
|
|
string msg_lines[];
|
|
uchar lines_size=0;
|
|
double curLot;
|
|
int h;
|
|
double buf0[];
|
|
double buf1[];
|
|
double buf2[];
|
|
int cur_offset;
|
|
bool noLong=false;
|
|
bool noShort=false;
|
|
datetime Old_Time=0;
|
|
double LastLong=0;
|
|
double LastShort=0;
|
|
|
|
struct translate{
|
|
string err1;
|
|
string err2;
|
|
string err3;
|
|
string err4;
|
|
string err5;
|
|
string err6;
|
|
string err7;
|
|
string err8;
|
|
string err9;
|
|
string err64;
|
|
string err65;
|
|
string err128;
|
|
string err129;
|
|
string err130;
|
|
string err131;
|
|
string err132;
|
|
string err133;
|
|
string err134;
|
|
string err135;
|
|
string err136;
|
|
string err137;
|
|
string err138;
|
|
string err139;
|
|
string err140;
|
|
string err141;
|
|
string err145;
|
|
string err146;
|
|
string err147;
|
|
string err148;
|
|
string err0;
|
|
string retcode;
|
|
string retcode10004;
|
|
string retcode10006;
|
|
string retcode10007;
|
|
string retcode10010;
|
|
string retcode10011;
|
|
string retcode10012;
|
|
string retcode10013;
|
|
string retcode10014;
|
|
string retcode10015;
|
|
string retcode10016;
|
|
string retcode10017;
|
|
string retcode10018;
|
|
string retcode10019;
|
|
string retcode10020;
|
|
string retcode10021;
|
|
string retcode10022;
|
|
string retcode10023;
|
|
string retcode10024;
|
|
string retcode10025;
|
|
string retcode10026;
|
|
string retcode10027;
|
|
string retcode10028;
|
|
string retcode10029;
|
|
string retcode10030;
|
|
string retcode10031;
|
|
string retcode10032;
|
|
string retcode10033;
|
|
string retcode10034;
|
|
string retcode10035;
|
|
string retcode10036;
|
|
string retcode10038;
|
|
string retcode10039;
|
|
string retcode10040;
|
|
string retcode10041;
|
|
string retcode10042;
|
|
string retcode10043;
|
|
string retcode10044;
|
|
};
|
|
translate langs;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
init_lang();
|
|
|
|
cur_offset=gridStep;
|
|
if(_Digits==5 || _Digits==3){
|
|
cur_offset*=10;
|
|
}
|
|
|
|
#ifdef __MQL5__
|
|
if(MA_PERIOD>0){
|
|
h = iMA(_Symbol, MA_Timeframe, MA_PERIOD, 0, MODE_SMA, PRICE_CLOSE);
|
|
}
|
|
#endif
|
|
|
|
if(!MQLInfoInteger(MQL_TRADE_ALLOWED)){
|
|
Comment("Expert Advisor not allowed to trade! ("+(string) EA_Magic+")");
|
|
}
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//---
|
|
ObjectsDeleteAll(0, prefix_graph);
|
|
#ifdef __MQL5__
|
|
if( MA_PERIOD>0 ){
|
|
IndicatorRelease(h);
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick(){
|
|
if( equityLess>0 && AccountInfoDouble(ACCOUNT_BALANCE)-AccountInfoDouble(ACCOUNT_EQUITY)>= equityLess ){
|
|
closeAllPos();
|
|
}
|
|
if( checkTakeProfit()){
|
|
closeAllPos();
|
|
}
|
|
if( !pdxIsNewBar() ){
|
|
return;
|
|
}
|
|
SymbolInfoTick(_Symbol, lastme);
|
|
if( lastme.bid==0 ){
|
|
return;
|
|
}
|
|
curLot=Lot;
|
|
|
|
getmeinfo_btn(_Symbol, EA_Magic);
|
|
startCheckPositions(EA_Magic);
|
|
|
|
}
|
|
void startCheckPositions(int magic){
|
|
if( gridStepCount>0 && (gridStepCount<=LongPos || gridStepCount<=ShortPos ) ){
|
|
return;
|
|
}
|
|
if( LongPos==0 && ShortPos == 0 ){
|
|
checkDirection();
|
|
}
|
|
|
|
if( LongPos + ShortPos == 0 ){
|
|
if(!noLong){
|
|
if(!pdxSendOrder(MY_BUY, lastme.bid, 0, 0, curLot, 0, "", _Symbol, magic)){
|
|
}
|
|
}else if(!noShort){
|
|
if(!pdxSendOrder(MY_SELL, lastme.ask, 0, 0, curLot, 0, "", _Symbol, magic)){
|
|
}
|
|
}
|
|
}else{
|
|
if(LongPos>0 ){
|
|
switch(typeLot){
|
|
case MY_ARIFMET:
|
|
curLot=Lot*LongPos;
|
|
break;
|
|
case MY_GEOMET:
|
|
if(LongPos>1) curLot=Lot*(MathPow(2, LongPos-1));
|
|
break;
|
|
}
|
|
if(LastLong-lastme.ask >= cur_offset*SymbolInfoDouble(_Symbol, SYMBOL_POINT) ){
|
|
if( gridStepCountClose>0 && gridStepCountClose==LongPos ){
|
|
closeAllPos(MY_ALLPOS, magic);
|
|
return;
|
|
}
|
|
if(!pdxSendOrder(MY_BUY, lastme.bid, 0, 0, curLot, 0, "", _Symbol, magic)){
|
|
}
|
|
}
|
|
}
|
|
if(ShortPos>0 ){
|
|
switch(typeLot){
|
|
case MY_ARIFMET:
|
|
curLot=Lot*ShortPos;
|
|
break;
|
|
case MY_GEOMET:
|
|
if(ShortPos>1) curLot=Lot*(MathPow(2, ShortPos-1));
|
|
|
|
break;
|
|
}
|
|
if(lastme.bid-LastShort >= cur_offset*SymbolInfoDouble(_Symbol, SYMBOL_POINT) ){
|
|
if( gridStepCountClose>0 && gridStepCountClose==ShortPos ){
|
|
closeAllPos(MY_ALLPOS, magic);
|
|
return;
|
|
}
|
|
if(!pdxSendOrder(MY_SELL, lastme.ask, 0, 0, curLot, 0, "", _Symbol, magic)){
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void checkDirection(){
|
|
noLong=false;
|
|
noShort=false;
|
|
|
|
if(MA_PERIOD>0){
|
|
#ifdef __MQL5__
|
|
CopyBuffer(h, 0, 0, 1, buf0);
|
|
if( buf0[0]>lastme.bid ){
|
|
noLong=true;
|
|
}else if( buf0[0]<lastme.bid ){
|
|
noShort=true;
|
|
}
|
|
#else
|
|
if( iMA(_Symbol, MA_Timeframe, MA_PERIOD, 0, MODE_SMA, PRICE_CLOSE, 0)>lastme.bid ){
|
|
noLong=true;
|
|
}else{
|
|
noShort=true;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if( SERIES_count>0 ){
|
|
MqlRates rates[];
|
|
ArraySetAsSeries(rates, true);
|
|
if( CopyRates( _Symbol, SERIES_Timeframe, 1, SERIES_count, rates)==SERIES_count ){
|
|
bool isOkLong=true;
|
|
bool isOkShort=true;
|
|
|
|
for( int i=0; i<SERIES_count; i++ ){
|
|
if( rates[i].close>rates[i].open ){
|
|
switch(SERIES_type){
|
|
case MY_SERIES_MINUS:
|
|
isOkLong=false;
|
|
break;
|
|
default:
|
|
isOkShort=false;
|
|
}
|
|
}else if( rates[i].close<rates[i].open ){
|
|
switch(SERIES_type){
|
|
case MY_SERIES_MINUS:
|
|
isOkShort=false;
|
|
break;
|
|
default:
|
|
isOkLong=false;
|
|
}
|
|
}
|
|
if( !isOkShort && !isOkLong ){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!isOkShort){
|
|
noShort=true;
|
|
}
|
|
if(!isOkLong){
|
|
noLong=true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool BARS_noLong=false;
|
|
bool BARS_noShort=false;
|
|
if(BARS_enabled ){
|
|
MqlRates rates[];
|
|
ArraySetAsSeries(rates, true);
|
|
if( CopyRates( _Symbol, BARS_Timeframe, 0, 2, rates)==2 ){
|
|
if( rates[1].close > rates[1].open ){
|
|
BARS_noShort=true;
|
|
}else if( rates[1].close < rates[1].open ){
|
|
BARS_noLong=true;
|
|
}else{
|
|
BARS_noShort=true;
|
|
BARS_noLong=true;
|
|
}
|
|
}
|
|
if( BARS_noLong ){
|
|
noLong=true;
|
|
}
|
|
if( BARS_noShort ){
|
|
noShort=true;
|
|
}
|
|
}
|
|
|
|
if(noGLong) noLong=true;
|
|
if(noGShort) noShort=true;
|
|
|
|
}
|
|
bool pdxIsNewBar(){
|
|
datetime New_Time[1];
|
|
|
|
if(CopyTime(_Symbol,_Period,0,1,New_Time)>0){
|
|
if(Old_Time!=New_Time[0]){
|
|
Old_Time=New_Time[0];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool checkTakeProfit(TypeOfPos type = MY_ALLPOS, int magic = 0){
|
|
if( takeProfit<=0 ) return false;
|
|
double curProfit=0;
|
|
double profit=0;
|
|
if( magic==0 ){
|
|
magic=EA_Magic;
|
|
}
|
|
|
|
#ifdef __MQL5__
|
|
int cntMyPos=PositionsTotal();
|
|
for(int ti=cntMyPos-1; ti>=0; ti--){
|
|
if(PositionGetSymbol(ti)!=_Symbol) continue;
|
|
if(magic>0 && PositionGetInteger(POSITION_MAGIC)!=magic) continue;
|
|
if(type==MY_BUY && PositionGetInteger(POSITION_TYPE)!=POSITION_TYPE_BUY ) continue;
|
|
if(type==MY_SELL && PositionGetInteger(POSITION_TYPE)!=POSITION_TYPE_SELL ) continue;
|
|
|
|
profit+=PositionGetDouble(POSITION_PROFIT);
|
|
profit+=PositionGetDouble(POSITION_SWAP);
|
|
}
|
|
#else
|
|
int cntMyPos=OrdersTotal();
|
|
if(cntMyPos>0){
|
|
for(int ti=cntMyPos-1; ti>=0; ti--){
|
|
if(OrderSelect(ti,SELECT_BY_POS,MODE_TRADES)==false) continue;
|
|
if( OrderType()==OP_BUY || OrderType()==OP_SELL ){}else{ continue; }
|
|
if(OrderSymbol()!=_Symbol) continue;
|
|
if(magic>0 && OrderMagicNumber()!=magic) continue;
|
|
if(type==MY_BUY && OrderType()!=OP_BUY ) continue;
|
|
if(type==MY_SELL && OrderType()!=OP_SELL ) continue;
|
|
|
|
profit+=OrderCommission();
|
|
profit+=OrderProfit();
|
|
profit+=OrderSwap();
|
|
}
|
|
}
|
|
#endif
|
|
if( takeProfit1step>0 && (LongPos+ShortPos)==1 ){
|
|
if(profit>takeProfit1step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit2step>0 && (LongPos+ShortPos)==2 ){
|
|
if(profit>takeProfit2step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit4step>0 && (LongPos+ShortPos)==4 ){
|
|
if(profit>takeProfit4step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit5step>0 && (LongPos+ShortPos)==5 ){
|
|
if(profit>takeProfit5step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit6step>0 && (LongPos+ShortPos)==6 ){
|
|
if(profit>takeProfit6step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit7step>0 && (LongPos+ShortPos)==7 ){
|
|
if(profit>takeProfit7step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit8step>0 && (LongPos+ShortPos)==8 ){
|
|
if(profit>takeProfit8step){
|
|
return true;
|
|
}
|
|
}else if( takeProfit9step>0 && (LongPos+ShortPos)==9 ){
|
|
if(profit>takeProfit9step){
|
|
return true;
|
|
}
|
|
}else{
|
|
if(profit>takeProfit){
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void closeAllPos(TypeOfPos type = MY_ALLPOS, int magic = 0){
|
|
if( magic==0 ){
|
|
magic=EA_Magic;
|
|
}
|
|
#ifdef __MQL5__
|
|
int cntMyPos=PositionsTotal();
|
|
for(int ti=cntMyPos-1; ti>=0; ti--){
|
|
if(PositionGetSymbol(ti)!=_Symbol) continue;
|
|
if(magic>0 && PositionGetInteger(POSITION_MAGIC)!=magic) continue;
|
|
if(type==MY_BUY && PositionGetInteger(POSITION_TYPE)!=POSITION_TYPE_BUY ) continue;
|
|
if(type==MY_SELL && PositionGetInteger(POSITION_TYPE)!=POSITION_TYPE_SELL ) continue;
|
|
|
|
Trade.PositionClose(PositionGetInteger(POSITION_TICKET));
|
|
}
|
|
int cntMyPosO=OrdersTotal();
|
|
for(int ti=cntMyPosO-1; ti>=0; ti--){
|
|
ulong orderTicket=OrderGetTicket(ti);
|
|
if(OrderGetString(ORDER_SYMBOL)!=_Symbol) continue;
|
|
if(magic>0 && OrderGetInteger(ORDER_MAGIC)!=magic) continue;
|
|
if(type==MY_BUY && OrderGetInteger(ORDER_TYPE)!=ORDER_TYPE_BUY_STOP ) continue;
|
|
if(type==MY_SELL && OrderGetInteger(ORDER_TYPE)!=ORDER_TYPE_SELL_STOP ) continue;
|
|
|
|
Trade.OrderDelete(orderTicket);
|
|
}
|
|
#else
|
|
int cntMyPos=OrdersTotal();
|
|
if(cntMyPos>0){
|
|
for(int ti=cntMyPos-1; ti>=0; ti--){
|
|
if(OrderSelect(ti,SELECT_BY_POS,MODE_TRADES)==false) continue;
|
|
if( OrderSymbol()!=_Symbol ) continue;
|
|
if(magic>0 && OrderMagicNumber()!=magic) continue;
|
|
|
|
if( OrderType()==OP_BUY ){
|
|
if(type==MY_SELL) continue;
|
|
MqlTick latest_price;
|
|
if(!SymbolInfoTick(OrderSymbol(),latest_price)){
|
|
Alert(GetLastError());
|
|
return;
|
|
}
|
|
if(!OrderClose(OrderTicket(), OrderLots(),latest_price.bid,100)){
|
|
}
|
|
}else if(OrderType()==OP_SELL){
|
|
if(type==MY_BUY) continue;
|
|
MqlTick latest_price;
|
|
if(!SymbolInfoTick(OrderSymbol(),latest_price)){
|
|
Alert(GetLastError());
|
|
return;
|
|
}
|
|
if(!OrderClose(OrderTicket(), OrderLots(),latest_price.ask,100)){
|
|
}
|
|
}else{
|
|
if(type==MY_BUY && OrderType()!=OP_BUYSTOP ) continue;
|
|
if(type==MY_SELL && OrderType()!=OP_SELLSTOP ) continue;
|
|
if(!OrderDelete(OrderTicket())){
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
// remove the position closing button
|
|
if(ObjectFind(0, prefix_graph+"delall")>0){
|
|
ObjectDelete(0, prefix_graph+"delall");
|
|
}
|
|
|
|
}
|
|
bool pdxSendOrder(TypeOfPos mytype, double price, double sl, double tp, double volume, ulong position=0, string comment="", string sym="", int magic=0){
|
|
if( !StringLen(sym) ){
|
|
sym=_Symbol;
|
|
}
|
|
if( magic==0 ){
|
|
magic=EA_Magic;
|
|
}
|
|
int curDigits=(int) SymbolInfoInteger(sym, SYMBOL_DIGITS);
|
|
if(sl>0){
|
|
sl=NormalizeDouble(sl,curDigits);
|
|
}
|
|
if(tp>0){
|
|
tp=NormalizeDouble(tp,curDigits);
|
|
}
|
|
if(price>0){
|
|
price=NormalizeDouble(price,curDigits);
|
|
}else{
|
|
#ifdef __MQL5__
|
|
#else
|
|
MqlTick latest_price;
|
|
SymbolInfoTick(sym,latest_price);
|
|
if( mytype == MY_SELL ){
|
|
price=latest_price.ask;
|
|
}else if( mytype == MY_BUY ){
|
|
price=latest_price.bid;
|
|
}
|
|
#endif
|
|
}
|
|
if( StringLen(my_cmt) && comment=="" ){
|
|
comment=my_cmt;
|
|
}
|
|
#ifdef __MQL5__
|
|
ENUM_TRADE_REQUEST_ACTIONS action=TRADE_ACTION_DEAL;
|
|
ENUM_ORDER_TYPE type=ORDER_TYPE_BUY;
|
|
switch(mytype){
|
|
case MY_BUY:
|
|
action=TRADE_ACTION_DEAL;
|
|
type=ORDER_TYPE_BUY;
|
|
break;
|
|
case MY_BUYSLTP:
|
|
action=TRADE_ACTION_SLTP;
|
|
type=ORDER_TYPE_BUY;
|
|
break;
|
|
case MY_BUYSTOP:
|
|
action=TRADE_ACTION_PENDING;
|
|
type=ORDER_TYPE_BUY_STOP;
|
|
break;
|
|
case MY_BUYLIMIT:
|
|
action=TRADE_ACTION_PENDING;
|
|
type=ORDER_TYPE_BUY_LIMIT;
|
|
break;
|
|
case MY_SELL:
|
|
action=TRADE_ACTION_DEAL;
|
|
type=ORDER_TYPE_SELL;
|
|
break;
|
|
case MY_SELLSLTP:
|
|
action=TRADE_ACTION_SLTP;
|
|
type=ORDER_TYPE_SELL;
|
|
break;
|
|
case MY_SELLSTOP:
|
|
action=TRADE_ACTION_PENDING;
|
|
type=ORDER_TYPE_SELL_STOP;
|
|
break;
|
|
case MY_SELLLIMIT:
|
|
action=TRADE_ACTION_PENDING;
|
|
type=ORDER_TYPE_SELL_LIMIT;
|
|
break;
|
|
}
|
|
|
|
MqlTradeRequest mrequest;
|
|
MqlTradeResult mresult;
|
|
ZeroMemory(mrequest);
|
|
|
|
mrequest.action = action;
|
|
mrequest.sl = sl;
|
|
mrequest.tp = tp;
|
|
mrequest.symbol = sym;
|
|
if(position>0){
|
|
mrequest.position = position;
|
|
}
|
|
if(StringLen(comment)){
|
|
mrequest.comment=comment;
|
|
}
|
|
if(action!=TRADE_ACTION_SLTP){
|
|
if(price>0){
|
|
mrequest.price = price;
|
|
}
|
|
if(volume>0){
|
|
mrequest.volume = volume;
|
|
}
|
|
mrequest.type = type;
|
|
mrequest.magic = magic;
|
|
switch(useORDER_FILLING_RETURN){
|
|
case FOK:
|
|
mrequest.type_filling = ORDER_FILLING_FOK;
|
|
break;
|
|
case RETURN:
|
|
mrequest.type_filling = ORDER_FILLING_RETURN;
|
|
break;
|
|
case IOC:
|
|
mrequest.type_filling = ORDER_FILLING_IOC;
|
|
break;
|
|
}
|
|
mrequest.deviation=100;
|
|
}
|
|
if(OrderSend(mrequest,mresult)){
|
|
if(mresult.retcode==10009 || mresult.retcode==10008){
|
|
if(action!=TRADE_ACTION_SLTP){
|
|
switch(type){
|
|
case ORDER_TYPE_BUY:
|
|
// Alert("Order Buy #:",mresult.order," sl",sl," tp",tp," p",price," !!");
|
|
break;
|
|
case ORDER_TYPE_SELL:
|
|
// Alert("Order Sell #:",mresult.order," sl",sl," tp",tp," p",price," !!");
|
|
break;
|
|
}
|
|
}else{
|
|
// Alert("Order Modify SL #:",mresult.order," sl",sl," tp",tp," !!");
|
|
}
|
|
return true;
|
|
}else{
|
|
msgErr(GetLastError(), mresult.retcode);
|
|
}
|
|
}
|
|
#else
|
|
int type=OP_BUY;
|
|
switch(mytype){
|
|
case MY_BUY:
|
|
type=OP_BUY;
|
|
break;
|
|
case MY_BUYSTOP:
|
|
type=OP_BUYSTOP;
|
|
break;
|
|
case MY_BUYLIMIT:
|
|
type=OP_BUYLIMIT;
|
|
break;
|
|
case MY_SELL:
|
|
type=OP_SELL;
|
|
break;
|
|
case MY_SELLSTOP:
|
|
type=OP_SELLSTOP;
|
|
break;
|
|
case MY_SELLLIMIT:
|
|
type=OP_SELLLIMIT;
|
|
break;
|
|
}
|
|
|
|
if(OrderSend(sym, type, volume, price, 100, sl, tp, comment, magic, 0)<0){
|
|
msgErr(GetLastError());
|
|
}else{
|
|
switch(type){
|
|
case OP_BUY:
|
|
Alert("Order Buy sl",sl," tp",tp," p",price," !!");
|
|
break;
|
|
case OP_SELL:
|
|
Alert("Order Sell sl",sl," tp",tp," p",price," !!");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
void msgErr(int err, int retcode=0){
|
|
string curErr="";
|
|
switch(err){
|
|
case 1:
|
|
curErr=langs.err1;
|
|
break;
|
|
case 2:
|
|
curErr=langs.err2;
|
|
break;
|
|
case 3:
|
|
curErr=langs.err3;
|
|
break;
|
|
case 4:
|
|
curErr=langs.err4;
|
|
break;
|
|
case 5:
|
|
curErr=langs.err5;
|
|
break;
|
|
case 6:
|
|
curErr=langs.err6;
|
|
break;
|
|
case 7:
|
|
curErr=langs.err7;
|
|
break;
|
|
case 8:
|
|
curErr=langs.err8;
|
|
break;
|
|
case 9:
|
|
curErr=langs.err9;
|
|
break;
|
|
case 64:
|
|
curErr=langs.err64;
|
|
break;
|
|
case 65:
|
|
curErr=langs.err65;
|
|
break;
|
|
case 128:
|
|
curErr=langs.err128;
|
|
break;
|
|
case 129:
|
|
curErr=langs.err129;
|
|
break;
|
|
case 130:
|
|
curErr=langs.err130;
|
|
break;
|
|
case 131:
|
|
curErr=langs.err131;
|
|
break;
|
|
case 132:
|
|
curErr=langs.err132;
|
|
break;
|
|
case 133:
|
|
curErr=langs.err133;
|
|
break;
|
|
case 134:
|
|
curErr=langs.err134;
|
|
break;
|
|
case 135:
|
|
curErr=langs.err135;
|
|
break;
|
|
case 136:
|
|
curErr=langs.err136;
|
|
break;
|
|
case 137:
|
|
curErr=langs.err137;
|
|
break;
|
|
case 138:
|
|
curErr=langs.err138;
|
|
break;
|
|
case 139:
|
|
curErr=langs.err139;
|
|
break;
|
|
case 140:
|
|
curErr=langs.err140;
|
|
break;
|
|
case 141:
|
|
curErr=langs.err141;
|
|
break;
|
|
case 145:
|
|
curErr=langs.err145;
|
|
break;
|
|
case 146:
|
|
curErr=langs.err146;
|
|
break;
|
|
case 147:
|
|
curErr=langs.err147;
|
|
break;
|
|
case 148:
|
|
curErr=langs.err148;
|
|
break;
|
|
default:
|
|
curErr=langs.err0+": "+(string) err;
|
|
}
|
|
if(retcode>0){
|
|
curErr+=" ";
|
|
switch(retcode){
|
|
case 10004:
|
|
curErr+=langs.retcode10004;
|
|
break;
|
|
case 10006:
|
|
curErr+=langs.retcode10006;
|
|
break;
|
|
case 10007:
|
|
curErr+=langs.retcode10007;
|
|
break;
|
|
case 10010:
|
|
curErr+=langs.retcode10010;
|
|
break;
|
|
case 10011:
|
|
curErr+=langs.retcode10011;
|
|
break;
|
|
case 10012:
|
|
curErr+=langs.retcode10012;
|
|
break;
|
|
case 10013:
|
|
curErr+=langs.retcode10013;
|
|
break;
|
|
case 10014:
|
|
curErr+=langs.retcode10014;
|
|
break;
|
|
case 10015:
|
|
curErr+=langs.retcode10015;
|
|
break;
|
|
case 10016:
|
|
curErr+=langs.retcode10016;
|
|
break;
|
|
case 10017:
|
|
curErr+=langs.retcode10017;
|
|
break;
|
|
case 10018:
|
|
curErr+=langs.retcode10018;
|
|
break;
|
|
case 10019:
|
|
curErr+=langs.retcode10019;
|
|
break;
|
|
case 10020:
|
|
curErr+=langs.retcode10020;
|
|
break;
|
|
case 10021:
|
|
curErr+=langs.retcode10021;
|
|
break;
|
|
case 10022:
|
|
curErr+=langs.retcode10022;
|
|
break;
|
|
case 10023:
|
|
curErr+=langs.retcode10023;
|
|
break;
|
|
case 10024:
|
|
curErr+=langs.retcode10024;
|
|
break;
|
|
case 10025:
|
|
curErr+=langs.retcode10025;
|
|
break;
|
|
case 10026:
|
|
curErr+=langs.retcode10026;
|
|
break;
|
|
case 10027:
|
|
curErr+=langs.retcode10027;
|
|
break;
|
|
case 10028:
|
|
curErr+=langs.retcode10028;
|
|
break;
|
|
case 10029:
|
|
curErr+=langs.retcode10029;
|
|
break;
|
|
case 10030:
|
|
curErr+=langs.retcode10030;
|
|
break;
|
|
case 10031:
|
|
curErr+=langs.retcode10031;
|
|
break;
|
|
case 10032:
|
|
curErr+=langs.retcode10032;
|
|
break;
|
|
case 10033:
|
|
curErr+=langs.retcode10033;
|
|
break;
|
|
case 10034:
|
|
curErr+=langs.retcode10034;
|
|
break;
|
|
case 10035:
|
|
curErr+=langs.retcode10035;
|
|
break;
|
|
case 10036:
|
|
curErr+=langs.retcode10036;
|
|
break;
|
|
case 10038:
|
|
curErr+=langs.retcode10038;
|
|
break;
|
|
case 10039:
|
|
curErr+=langs.retcode10039;
|
|
break;
|
|
case 10040:
|
|
curErr+=langs.retcode10040;
|
|
break;
|
|
case 10041:
|
|
curErr+=langs.retcode10041;
|
|
break;
|
|
case 10042:
|
|
curErr+=langs.retcode10042;
|
|
break;
|
|
case 10043:
|
|
curErr+=langs.retcode10043;
|
|
break;
|
|
case 10044:
|
|
curErr+=langs.retcode10044;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Alert(curErr);
|
|
}
|
|
|
|
void init_lang(){
|
|
switch(LANG){
|
|
case MY_ENG:
|
|
langs.err1="No error, but unknown result. (1)";
|
|
langs.err2="General error (2)";
|
|
langs.err3="Incorrect parameters (3)";
|
|
langs.err4="Trade server busy (4)";
|
|
langs.err5="Old client terminal version (5)";
|
|
langs.err6="No connection to trade server (6)";
|
|
langs.err7="Not enough rights (7)";
|
|
langs.err8="Too frequent requests (8)";
|
|
langs.err9="Invalid operation disruptive server operation (9)";
|
|
langs.err64="Account blocked (64)";
|
|
langs.err65="Invalid account number (65)";
|
|
langs.err128="Expired waiting period for transaction (128)";
|
|
langs.err129="Invalid price (129)";
|
|
langs.err130="Wrong stop loss (130)";
|
|
langs.err131="Wrong volume (131)";
|
|
langs.err132="Market closed (132)";
|
|
langs.err133="Trade prohibited (133)";
|
|
langs.err134="Not enough money to complete transaction. (134)";
|
|
langs.err135="Price changed (135)";
|
|
langs.err136="No prices (136)";
|
|
langs.err137="Broker busy (137)";
|
|
langs.err138="New prices (138)";
|
|
langs.err139="Order blocked and already being processed (139)";
|
|
langs.err140="Only purchase allowed (140)";
|
|
langs.err141="Too many requests (141)";
|
|
langs.err145="Modification prohibited because order too close to market. (145)";
|
|
langs.err146="Trading subsystem busy (146)";
|
|
langs.err147="Using order expiration date prohibited by broker (147)";
|
|
langs.err148="Number of open and pending orders reached limit set by broker (148)";
|
|
langs.err0="Error occurred while running request";
|
|
langs.retcode="Reason";
|
|
langs.retcode10004="Requote";
|
|
langs.retcode10006="Request rejected";
|
|
langs.retcode10007="Request canceled by trader";
|
|
langs.retcode10010="Only part of request completed";
|
|
langs.retcode10011="Request processing error";
|
|
langs.retcode10012="Request canceled by timeout";
|
|
langs.retcode10013="Invalid request";
|
|
langs.retcode10014="Invalid volume in request";
|
|
langs.retcode10015="Invalid price in request";
|
|
langs.retcode10016="Invalid stops in request";
|
|
langs.retcode10017="Trade disabled";
|
|
langs.retcode10018="Market closed";
|
|
langs.retcode10019="Not enough money to complete request";
|
|
langs.retcode10020="Prices changed";
|
|
langs.retcode10021="No quotes to process request";
|
|
langs.retcode10022="Invalid order expiration date in request";
|
|
langs.retcode10023="Order state changed";
|
|
langs.retcode10024="Too frequent requests";
|
|
langs.retcode10025="No changes in request";
|
|
langs.retcode10026="Autotrading disabled by server";
|
|
langs.retcode10027="Autotrading disabled by client terminal";
|
|
langs.retcode10028="Request locked for processing";
|
|
langs.retcode10029="Order or position frozen";
|
|
langs.retcode10030="Invalid order filling type";
|
|
langs.retcode10031="No connection with trade server";
|
|
langs.retcode10032="Operation allowed only for live accounts";
|
|
langs.retcode10033="Number of pending orders reached limit";
|
|
langs.retcode10034="Volume of orders and positions for symbol reached limit";
|
|
langs.retcode10035="Incorrect or prohibited order type";
|
|
langs.retcode10036="Position with specified POSITION_IDENTIFIER already closed";
|
|
langs.retcode10038="Close volume exceeds current position volume";
|
|
langs.retcode10039="Close order already exists for specified position";
|
|
langs.retcode10040="Number of open items exceeded";
|
|
langs.retcode10041="Pending order activation request rejected, order canceled";
|
|
langs.retcode10042="Only long positions allowed";
|
|
langs.retcode10043="Only short positions allowed";
|
|
langs.retcode10044="Only position closing allowed";
|
|
break;
|
|
case MY_RUS:
|
|
langs.err0="Во время выполнения запроса произошла ошибка";
|
|
langs.err1="Нет ошибки, но результат неизвестен (1)";
|
|
langs.err2="Общая ошибка (2)";
|
|
langs.err3="Неправильные параметры (3)";
|
|
langs.err4="Торговый сервер занят (4)";
|
|
langs.err5="Старая версия клиентского терминала (5)";
|
|
langs.err6="Нет связи с торговым сервером (6)";
|
|
langs.err7="Недостаточно прав (7)";
|
|
langs.err8="Слишком частые запросы (8)";
|
|
langs.err9="Недопустимая операция нарушающая функционирование сервера (9)";
|
|
langs.err64="Счет заблокирован (64)";
|
|
langs.err65="Неправильный номер счета (65)";
|
|
langs.err128="Истек срок ожидания совершения сделки (128)";
|
|
langs.err129="Неправильная цена (129)";
|
|
langs.err130="Неправильные стопы (130)";
|
|
langs.err131="Неправильный объем (131)";
|
|
langs.err132="Рынок закрыт (132)";
|
|
langs.err133="Торговля запрещена (133)";
|
|
langs.err134="Недостаточно денег для совершения операции (134)";
|
|
langs.err135="Цена изменилась (135)";
|
|
langs.err136="Нет цен (136)";
|
|
langs.err137="Брокер занят (137)";
|
|
langs.err138="Новые цены (138)";
|
|
langs.err139="Ордер заблокирован и уже обрабатывается (139)";
|
|
langs.err140="Разрешена только покупка (140)";
|
|
langs.err141="Слишком много запросов (141)";
|
|
langs.err145="Модификация запрещена, так как ордер слишком близок к рынку (145)";
|
|
langs.err146="Подсистема торговли занята (146)";
|
|
langs.err147="Использование даты истечения ордера запрещено брокером (147)";
|
|
langs.err148="Количество открытых и отложенных ордеров достигло предела, установленного брокером (148)";
|
|
langs.retcode="Причина";
|
|
langs.retcode10004="Реквота";
|
|
langs.retcode10006="Запрос отклонен";
|
|
langs.retcode10007="Запрос отменен трейдером";
|
|
langs.retcode10010="Заявка выполнена частично";
|
|
langs.retcode10011="Ошибка обработки запроса";
|
|
langs.retcode10012="Запрос отменен по истечению времени";
|
|
langs.retcode10013="Неправильный запрос";
|
|
langs.retcode10014="Неправильный объем в запросе";
|
|
langs.retcode10015="Неправильная цена в запросе";
|
|
langs.retcode10016="Неправильные стопы в запросе";
|
|
langs.retcode10017="Торговля запрещена";
|
|
langs.retcode10018="Рынок закрыт";
|
|
langs.retcode10019="Нет достаточных денежных средств для выполнения запроса";
|
|
langs.retcode10020="Цены изменились";
|
|
langs.retcode10021="Отсутствуют котировки для обработки запроса";
|
|
langs.retcode10022="Неверная дата истечения ордера в запросе";
|
|
langs.retcode10023="Состояние ордера изменилось";
|
|
langs.retcode10024="Слишком частые запросы";
|
|
langs.retcode10025="В запросе нет изменений";
|
|
langs.retcode10026="Автотрейдинг запрещен сервером";
|
|
langs.retcode10027="Автотрейдинг запрещен клиентским терминалом";
|
|
langs.retcode10028="Запрос заблокирован для обработки";
|
|
langs.retcode10029="Ордер или позиция заморожены";
|
|
langs.retcode10030="Указан неподдерживаемый тип исполнения ордера по остатку ";
|
|
langs.retcode10031="Нет соединения с торговым сервером";
|
|
langs.retcode10032="Операция разрешена только для реальных счетов";
|
|
langs.retcode10033="Достигнут лимит на количество отложенных ордеров";
|
|
langs.retcode10034="Достигнут лимит на объем ордеров и позиций для данного символа";
|
|
langs.retcode10035="Неверный или запрещённый тип ордера";
|
|
langs.retcode10036="Позиция с указанным POSITION_IDENTIFIER уже закрыта";
|
|
langs.retcode10038="Закрываемый объем превышает текущий объем позиции";
|
|
langs.retcode10039="Для указанной позиции уже есть ордер на закрытие";
|
|
langs.retcode10040="Количество открытых позиций превышено";
|
|
langs.retcode10041="Запрос на активацию отложенного ордера отклонен, а сам ордер отменен";
|
|
langs.retcode10042="Разрешены только длинные позиции";
|
|
langs.retcode10043="Разрешены только короткие позиции";
|
|
langs.retcode10044="Разрешено только закрывать существующие позиции";
|
|
break;
|
|
}
|
|
}
|
|
void getmeinfo_btn(string symname, int magic){
|
|
double profit=0;
|
|
double positionExist=false;
|
|
LongVol=0;
|
|
ShortVol=0;
|
|
datetime oldTimeLong=0;
|
|
datetime oldTimeShort=0;
|
|
|
|
LastLong=0;
|
|
LastShort=0;
|
|
|
|
LongPos=0;
|
|
ShortPos=0;
|
|
|
|
// count the number of open Long and Short positions,
|
|
// as well as their total profit
|
|
#ifdef __MQL5__
|
|
int cntMyPos=PositionsTotal();
|
|
for(int ti=cntMyPos-1; ti>=0; ti--){
|
|
if(PositionGetSymbol(ti)!=symname) continue;
|
|
if(magic>0 && PositionGetInteger(POSITION_MAGIC)!=magic) continue;
|
|
|
|
positionExist=true;
|
|
|
|
profit+=PositionGetDouble(POSITION_PROFIT);
|
|
profit+=PositionGetDouble(POSITION_SWAP);
|
|
|
|
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY){
|
|
LongVol+=PositionGetDouble(POSITION_VOLUME);
|
|
LongPos++;
|
|
if( !oldTimeLong || oldTimeLong<PositionGetInteger(POSITION_TIME) ){
|
|
oldTimeLong=(datetime) PositionGetInteger(POSITION_TIME);
|
|
LastLong=PositionGetDouble(POSITION_PRICE_OPEN);
|
|
}
|
|
}else{
|
|
ShortVol+=PositionGetDouble(POSITION_VOLUME);
|
|
ShortPos++;
|
|
if( !oldTimeShort || oldTimeShort<PositionGetInteger(POSITION_TIME) ){
|
|
oldTimeShort=(datetime) PositionGetInteger(POSITION_TIME);
|
|
LastShort=PositionGetDouble(POSITION_PRICE_OPEN);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
int cntMyPos=OrdersTotal();
|
|
if(cntMyPos>0){
|
|
for(int ti=cntMyPos-1; ti>=0; ti--){
|
|
if(OrderSelect(ti,SELECT_BY_POS,MODE_TRADES)==false) continue;
|
|
if( OrderType()==OP_BUY || OrderType()==OP_SELL ){}else{ continue; }
|
|
if(OrderSymbol()!=symname) continue;
|
|
if(magic>0 && OrderMagicNumber()!=magic) continue;
|
|
|
|
positionExist=true;
|
|
|
|
profit+=OrderCommission();
|
|
profit+=OrderProfit();
|
|
profit+=OrderSwap();
|
|
|
|
if(OrderType()==OP_BUY){
|
|
LongVol+=OrderLots();
|
|
LongPos++;
|
|
if( !oldTimeLong || oldTimeLong<OrderOpenTime() ){
|
|
oldTimeLong=OrderOpenTime();
|
|
LastLong=OrderOpenPrice();
|
|
}
|
|
}else{
|
|
ShortVol+=OrderLots();
|
|
ShortPos++;
|
|
if( !oldTimeShort || oldTimeShort<OrderOpenTime() ){
|
|
oldTimeShort=OrderOpenTime();
|
|
LastShort=OrderOpenPrice();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// if there are open positions,
|
|
// then add the button for closing them
|
|
if(positionExist){
|
|
createObject(prefix_graph+"delall", 163, "Close all ("+(string) profit+")");
|
|
}else{
|
|
// otherwise, remove the position closing button
|
|
if(ObjectFind(0, prefix_graph+"delall")>0){
|
|
ObjectDelete(0, prefix_graph+"delall");
|
|
}
|
|
}
|
|
|
|
// update the current chart to implement
|
|
// changes
|
|
ChartRedraw(0);
|
|
}
|
|
void createObject(string name, int weight, string title){
|
|
// if there is no 'name' button on the chart, create it
|
|
if(ObjectFind(0, name)<0){
|
|
// define the shift relative to the chart right angle where the button is to be displayed
|
|
long offset= ChartGetInteger(0, CHART_WIDTH_IN_PIXELS)-87;
|
|
long offsetY=0;
|
|
for(int ti=0; ti<ObjectsTotal((long) 0); ti++){
|
|
string objName= ObjectName(0, ti);
|
|
if( StringFind(objName, prefix_graph)<0 ){
|
|
continue;
|
|
}
|
|
long tmpOffset=ObjectGetInteger(0, objName, OBJPROP_YDISTANCE);
|
|
if( tmpOffset>offsetY){
|
|
offsetY=tmpOffset;
|
|
}
|
|
}
|
|
|
|
for(int ti=0; ti<ObjectsTotal((long) 0); ti++){
|
|
string objName= ObjectName(0, ti);
|
|
if( StringFind(objName, prefix_graph)<0 ){
|
|
continue;
|
|
}
|
|
long tmpOffset=ObjectGetInteger(0, objName, OBJPROP_YDISTANCE);
|
|
if( tmpOffset!=offsetY ){
|
|
continue;
|
|
}
|
|
|
|
tmpOffset=ObjectGetInteger(0, objName, OBJPROP_XDISTANCE);
|
|
if( tmpOffset>0 && tmpOffset<offset){
|
|
offset=tmpOffset;
|
|
}
|
|
}
|
|
offset-=(weight+1);
|
|
if(offset<0){
|
|
offset=ChartGetInteger(0, CHART_WIDTH_IN_PIXELS)-87;
|
|
offsetY+=25;
|
|
offset-=(weight+1);
|
|
}
|
|
|
|
ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
|
|
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,offset);
|
|
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,offsetY);
|
|
ObjectSetString(0,name,OBJPROP_TEXT, title);
|
|
ObjectSetInteger(0,name,OBJPROP_XSIZE,weight);
|
|
ObjectSetInteger(0,name,OBJPROP_FONTSIZE, 8);
|
|
ObjectSetInteger(0,name,OBJPROP_COLOR, clrBlack);
|
|
ObjectSetInteger(0,name,OBJPROP_YSIZE,25);
|
|
ObjectSetInteger(0,name,OBJPROP_BGCOLOR, clrLightGray);
|
|
ChartRedraw(0);
|
|
}else{
|
|
ObjectSetString(0,name,OBJPROP_TEXT, title);
|
|
}
|
|
}
|
|
|
|
void OnChartEvent(const int id, // event ID
|
|
const long& lparam, // event parameter of the long type
|
|
const double& dparam, // event parameter of the double type
|
|
const string& sparam) // event parameter of the string type
|
|
{
|
|
string text="";
|
|
switch(id){
|
|
case CHARTEVENT_OBJECT_CLICK:
|
|
// if the clicked button name is prefix_graph+"delall", then
|
|
if (sparam==prefix_graph+"delall"){
|
|
closeAllPos();
|
|
}
|
|
break;
|
|
}
|
|
} |