Expert Advisor


/* * Kijun Sen Robot * * Copyright ® 2005 Noam Koren (Questo indirizzo email è protetto dagli spambots. È necessario abilitare JavaScript per vederlo.) * * o Based on Akash discussion at Moneytech ("Great technique for beginners") * * o Disclaimer : Distributed for forward testing purposes. * This expert was never tested on a live account - use at your own risk! * In other words - DO NOT USE ON A LIVE ACCOUNT ! * * o Attach to 30 Minute chart * * * $Log: KSRobot.mq4,v $ * Revision 1.5 2005/10/18 11:10:09 noam * 1) Added alerts * * 2) Modified S/L rules to reduce average S/L size - if a bar closes with MA in the wrong direction exit if B/E was not hit yet. * * 3) Modified Entry rule - Wait for BID to cross KS for Long and ASK to cross down for Short. This helps to filter out faulty signals. * * 4) Modified Entry rule - only enter if KS is Horizontal OR in the same direction of entry. * * Revision 1.4 2005/10/08 18:19:58 noam * 1) Added slope: allows filtering out trades if the slope of KS line is too vertical (too = defined by user) * 2) Added optimized values per currency. This can be overrider by setting UseOptimizedValues to false. * 3) Added a comment to provide some information to the user while the expert is attached. * * Experimental * E1) Added two experimental stop loss tactics (not used unless by default): * a) PSAR * b) Exit if not at BE after X bars * * Revision 1.3 2005/09/21 01:00:47 noam * Use limit order / market order depending on current price * Do not clear cross value until order is sent * Added some printouts * * Revision 1.2 2005/09/20 17:11:12 noam * Added disclaimer * Added price normalization * Adjusted time limits to fit MT4 time * * Revision 1.1 2005/09/19 20:34:57 noam * Initial Kijun Sen Robot version * Backtested on 30M GBP/USD * */ /* * TODO: * * 1) Find a way to improve profit taking - TS is good but misses much of trendy moves. Maybe * switch to EMA signal once X pips are secure? * * 2) Find out why entering only once per bar hits performance. * * 3) Add 2% money management rule. * */ #property copyright "Noam Koren" /* expert specific parameters */ #define EXPERT_COLOR Yellow #define EXPERT_STRING "Kijun Sen Robot" #define EXPERT_MAGIC 13 #define UP 1 #define DOWN -1 #define NEUTRAL 0 /* Optimized results GBP/USD: 4.38 1000.00 8.38% StopLoss=50 BreakEven=9 TrailingStop=10 MAfilter=6 TakeProfit=120 EUR/USD: 2.68 1520.00 12.24% StopLoss=60 BreakEven=9 TrailingStop=6 MAfilter=6 TakeProfit=120 */ int MaxOpenPositions = 1; /* Default parameters. */ int TakeProfit = 120; /* default 120 */ extern int StopLoss = 50; /* 50 very imporant to allow for a substaintial movement in the other direction */ extern int BreakEven = 9; /* default = 9 */ extern int TrailingStop = 10; /* default 10 */ extern int MAfilter = 6; /* MA must be at least 6 pips away from KS in order to be valid */ extern bool UseOptimizedValues = true; /* MM */ extern double Lots = 1; int TenkanSen = 9; int KijunSen = 26; int Senkou = 52; /* globals */ double lastbid = 0.0; double lastask = 0.0; double longcross = 0.0; double shortcross = 0.0; double longentry = 0.0; double shortentry = 0.0; int daystart = 7; /* 5AM GMT */ int dayend = 19;/* 5PM GMT */ int MAdir = NEUTRAL; int precision = 4; int lastbar = 0; bool newbar = false; /* generic init functions */ int init() { if (UseOptimizedValues == true){ /* set parameters based on pair */ if (Symbol()=="GBPUSD") {StopLoss=50; BreakEven=9; TrailingStop=10; MAfilter=6;} if (Symbol()=="EURUSD") {StopLoss=60; BreakEven=9; TrailingStop=6; MAfilter=6;} } precision = SymbolPrecision(); lastbar = Time[0]; return(0); } int deinit(){ return(0); } /* expert specific utility functions */ int SymbolPrecision() { return (MarketInfo(Symbol(), MODE_DIGITS)); } int OpenPosition() { double KS = iIchimoku(NULL, 0, TenkanSen, KijunSen, Senkou, MODE_KIJUNSEN, 0); double KS1 = iIchimoku(NULL, 0, TenkanSen, KijunSen, Senkou, MODE_KIJUNSEN, 1); double KS2 = iIchimoku(NULL, 0, TenkanSen, KijunSen, Senkou, MODE_KIJUNSEN, 2); double Ema20 = iMA(NULL,0,20,0,MODE_LWMA,PRICE_CLOSE,0); double PEma20 = iMA(NULL,0,20,0,MODE_LWMA,PRICE_CLOSE,1); double PSAR = iSAR(NULL, 0, 0.02, 0.2, 0); /* fast parabolic for tight exits */ if (lastbid == 0.0) lastbid = Bid; if (lastask == 0.0) lastask = Ask; /* Make sure the time is right */ if ( Hour() < daystart || Hour() > dayend-1 ) return (0); /* KS cross */ if ( Open[0] < KS && lastbid < KS && Bid > KS && longcross == 0 && KS >= KS2) { /* the cross is only interesting if the KS line is above the MA */ if ( Ema20 < KS - MAfilter * Point ) { longcross = KS; shortcross = 0; } } if ( Open[0] > KS && lastask > KS && Ask < KS && shortcross == 0 && KS <= KS2) { /* the cross is only interesting if the KS line is under the MA */ if ( Ema20 > KS + MAfilter * Point ) { shortcross = KS; longcross = 0; } } /* check MA direction */ if ( PEma20 < Ema20 ){ MAdir = UP; } if ( PEma20 > Ema20 ){ MAdir = DOWN; } /* once the MA is pointing in the right direction set the the entry price to be the current KS */ if (MAdir == UP && longcross != 0 && longentry == 0){ longentry = NormalizeDouble( KS, precision ); return (1); } /* once the MA is pointing in the right direction set the the entry price to be the current KS */ if (MAdir == DOWN && shortcross != 0 && shortentry == 0){ shortentry = NormalizeDouble( KS, precision ); return (-1); } lastbid = Bid; lastask = Ask; return (0); } int ClosePosition() { double PEma20 = iMA(NULL,0,20,0,MODE_LWMA,PRICE_CLOSE,1); double PPEma20 = iMA(NULL,0,20,0,MODE_LWMA,PRICE_CLOSE,2); if ( OrderType() == OP_BUY ){ if (newbar && PEma20 < PPEma20 && OrderStopLoss() < OrderOpenPrice() ){ return (1); } } if ( OrderType() == OP_SELL ){ if (newbar && PEma20 > PPEma20 && OrderStopLoss() > OrderOpenPrice() ){ return (-1); } } return (0); } /* The expert logic */ int start() { int cnt, experttickets, ticket, total, i, pos, action=0, method; double hardstop; datetime ticketexpiration = 0; /* make sure that the char is valid */ if (Bars<100){ Print("Invalid chart: less than 100 bars!"); return (-1); } if ( ( Hour() < daystart || Hour() > dayend-1 ) ){ Comment("\nTrading halted. (will start again at ", daystart, " AM )\n"); } else { Comment("\nExpert is active. (will halt at ", dayend, " PM )\n"); Comment("\nTS = ", TrailingStop, " BE = ", BreakEven, " SL = ", StopLoss, " MAfilter = ", MAfilter,"\n"); } total=OrdersTotal(); if (Time[0] == lastbar) { newbar = false; } else { lastbar = Time[0]; newbar = true; } /* Only allow one open position at a time (per expert)- so if there is an open position - do not open another one. */ for(cnt=0,experttickets=0;cnt<total;cnt++) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && OrderMagicNumber() == EXPERT_MAGIC) { experttickets=experttickets+1; } } if(experttickets<MaxOpenPositions) { /* Set the number of lots - or exit if there is not enough margin */ Lots = Lots; ticketexpiration = CurTime() + PERIOD_M30 * 60; /* orders are valid for half an hour */ /* OpenPosition() has state so calling it again will mess up the results - this is why I call it * once and remember the return value before acting */ action = OpenPosition(); /* check for long position (BUY) possibility */ if ( action == 1 ) { if (Ask > longentry + 4 * Point) method = OP_BUYLIMIT; if (Ask == longentry) method = OP_BUY; if (Ask < longentry) { longentry = Ask; method = OP_BUY; } hardstop = NormalizeDouble( (longentry-StopLoss*Point), precision) ; Alert("KSRobot ", Symbol(), " Go Long @ ", longentry, "!"); ticket=OrderSend(Symbol(),method,Lots,longentry,4,hardstop,Ask+TakeProfit*Point,EXPERT_STRING,EXPERT_MAGIC,ticketexpiration,White); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) { Print("BUY LIMIT order sent : ",OrderOpenPrice(), "Ask = ", Ask, "\n" ); } longcross = 0; } else { Print("Error opening BUY LIMIT order : ",GetLastError(), " SL = ", hardstop, " Ask = ", Ask, " Entry = ", longentry, " TP =",Ask+TakeProfit*Point, " Method = ", method, "\n"); } longentry = 0; return(0); } /* check for short position (SELL) possibility */ if ( action == -1 ) { hardstop = NormalizeDouble( (shortentry+StopLoss*Point), precision) ; Alert("KSRobot ", Symbol(), " KS Go Short @ ", shortentry, "!"); if (Bid < shortentry - 4 * Point) method = OP_SELLLIMIT; if (Bid == shortentry) method = OP_SELL; if (Bid > shortentry) { shortentry = Bid; method = OP_SELL; } ticket=OrderSend(Symbol(),method,Lots,shortentry,4,hardstop,Bid-TakeProfit*Point,EXPERT_STRING,EXPERT_MAGIC,ticketexpiration,Red); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) { Print("SELL LIMIT order sent : ",OrderOpenPrice(), "Bid = ", Bid, "\n"); } shortcross = 0; } else { Print("Error opening SELL LIMIT order : ",GetLastError(), " SL = ", hardstop, " Bid = ", Bid, " Entry = ", shortentry, " TP =",Bid-TakeProfit*Point, "method = ", method, "\n" ); } shortentry = 0; return(0); } /* do nothing */ return(0); } /* if there are open positions - check if they need to be closed */ for(cnt=0;cnt<total;cnt++) { lastbid = Bid; lastask = Ask; OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); /* Check if there are positions that were opened by this expert for this symbol */ if( OrderType()<=OP_SELL && OrderSymbol()==Symbol() && OrderMagicNumber() == EXPERT_MAGIC ) { /* handle long position */ if(OrderType()==OP_BUY) { /* close if condition met */ if ( ClosePosition()==1 ) { OrderClose(OrderTicket(),OrderLots(),Bid,3,EXPERT_COLOR); return (0); } /* set BreakEven if set */ if (BreakEven>0){ if(Bid-OrderOpenPrice()>Point*BreakEven) { if(OrderStopLoss()<OrderOpenPrice()) { OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+Point*1,OrderTakeProfit(),0,Gray); } } } /* update trailing stop */ if(TrailingStop>0) { if(Bid-OrderOpenPrice()>Point*(TrailingStop)) { if(OrderStopLoss()<Bid-Point*TrailingStop) { OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Gray); return(0); } } } } else { /* handle short position */ /* close if condition met */ if (ClosePosition()==-1) { OrderClose( OrderTicket(),OrderLots(),Ask,3,EXPERT_COLOR ); return (0); } /* set BreakEven if set */ if (BreakEven>0){ if(OrderOpenPrice()-Ask>Point*BreakEven) { if(OrderStopLoss()>OrderOpenPrice()) { OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-Point*1,OrderTakeProfit(),0,Gray); } } } /* update trailing stop */ if(TrailingStop>0) { if(OrderOpenPrice()-Ask>Point*(TrailingStop)) { if(OrderStopLoss()>Ask+Point*TrailingStop) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Gray); return(0); } } } } } } return(0); }