// Goblin BiPolar Edition v.1.0 // by bluto @ www.forex-tsd.com // 12/20/2006 // // Here's a roughly cobbled version of Goblin that supports two EA routines in one - a buy side and a sell side running concurrently. // Although effective, the code isn't the most modular at this point. If the concept proves to be viable, I'll continue further // development to optimize shared subroutines between the two sub-EA routines. For now...play, test & be bodaceous! // // Modifications by alassio: // - Determine lot size of individual orders // - Scale lot sizes by account equity for compounding (replaces previous mm) // - Collect winner/loser statistics // - Allow usage of progressions after losers (experimental) // extern string FixedLotsFeature = "** Determine lot size of individual orders **"; extern double FixedLotsOrder1 = 2; extern double FixedLotsOrder2 = 2; extern double FixedLotsOrder3 = 1; extern double FixedLotsOrder4 = 3; extern double FixedLotsOrder5 = 4; extern double FixedLotsOrder6 = 5; extern double FixedLotsOrder7 = 0; extern double FixedLotsOrder8 = 0; extern double FixedLotsOrder9 = 0; extern double FixedLotsOrderLast = 0; extern string DynamicLotsFeature = "** Scale lots by account size for compounding **"; extern bool UseDynamicLots = true; extern double LotBaseEquity = 50000; extern double LotBaseSize = 1; extern string StatisticsFeature = "** Collect winner/loser statistics **"; extern double LoserLimit = -1000; extern double KellyFactor = 0.25; extern string ProgressionFeature = "** Use lot size progression after losers **"; extern bool UseProgression = false; extern bool UseGlobalProg = true; // Same progression for bus/sell orders extern int ProgressionModel = 2; // 1 = Dahl progression, 2 = reverse Dahl progression extern int MaxProgStep = 12; extern bool UseCycleProgSteps = false; extern string EntryFeature = "** Select entry signal parameters **"; extern bool UseRSX = false; extern bool UseConservativeRSX_Signals=false; // If true, we use tighter RSX 70/30 rules extern int RSX_Period=17; extern int RSX_Timeframe=60; extern bool UseJMATrend = true; extern int JMAPeriod = 28; extern int JMALag = 2; extern double JMAPointDiff = 2; extern bool UseSMATrendFilter=false; extern int TrendFilterSMATimeFrame=60; extern int TrendFilterFastSMAPeriod=65; extern int TrendFilterMediumSMAPeriod=20; extern int TrendFilterSlowSMAPeriod=7; extern string LongTradeParms = "** Goblin Buy Side Parameters **"; extern double LongTakeProfit = 10; // Profit Goal for the latest order opened extern double LongInitialStop = 10; // StopLoss extern double LongTrailingStop = 0; // Pips to trail the StopLoss extern int LongMaxTrades=6; // Maximum number of orders to open extern int LongPips=5; // Distance in Pips from one order to another extern int LongSecureProfit=0; // If profit made is bigger than SecureProfit we close the orders extern bool LongAccountProtection=false; // If one the account protection will be enabled, 0 is disabled extern int LongOrderstoProtect=0; // This number subtracted from LongMaxTrades is the number of open orders to enable the account protection. // Example: (LongMaxTrades=10) minus (OrderstoProtect=3)=7 orders need to be open before account protection is enabled. extern string ShortTradeParms = "** Goblin Sell Side Parameters **"; extern double ShortTakeProfit = 10; // Profit Goal for the latest order opened extern double ShortInitialStop = 10; // StopLoss extern double ShortTrailingStop = 0; // Pips to trail the StopLoss extern int ShortMaxTrades=6; // Maximum number of orders to open extern int ShortPips=5; // Distance in Pips from one order to another extern int ShortSecureProfit=0; // If profit made is bigger than SecureProfit we close the orders extern bool ShortAccountProtection=false; // If one the account protection will be enabled, 0 is disabled extern int ShortOrderstoProtect=0; // This number subtracted from LongMaxTrades is the number of open orders to enable the account protection. // Example: (LongMaxTrades=10) minus (OrderstoProtect=3)=7 orders need to be open before account protection is enabled. // Global internal parameters used by LongGoblin() buy order module: int LongMagicNumber = 0; // Magic number for the long orders placed int L_OpenOrders=0; int L_Count=0; int L_Slippage=5; double L_sl=0; double L_tp=0; double BuyPrice=0; double L_OrderLotSize=0; int L_Mode=0; int L_OrderType=0; bool L_ContinueOpening=true; double L_LastPrice=0; int L_PreviousOpenOrders=0; double L_Profit=0; int L_LastTicket=0; int L_LastType=0; double L_LastClosePrice=0; double L_LastLots=0; double L_PipValue=0; double L_OldProfit = 0; int L_ProgStep = 0; double L_ProgFactor = 1; int L_Winners = 0; int L_Losers = 0; double L_Balance = 0; double L_AccumulatedProfit = 0; // Global internal parameters used by ShortGoblin() sell order module: int ShortMagicNumber = 0; // Magic number for the short orders placed int S_OpenOrders=0; int S_Count=0; int S_Slippage=5; double S_sl=0; double S_tp=0; double SellPrice=0; double S_OrderLotSize=0; int S_Mode=0; int S_OrderType=0; bool S_ContinueOpening=true; double S_LastPrice=0; int S_PreviousOpenOrders=0; double S_Profit=0; int S_LastTicket=0; int S_LastType=0; double S_LastClosePrice=0; double S_LastLots=0; double S_PipValue=0; double S_OldProfit = 0; int S_ProgStep = 0; double S_ProgFactor = 1; int S_Winners = 0; int S_Losers = 0; double S_Balance = 0; double S_AccumulatedProfit = 0; // Global internal shared parameters double G_MinLotSize=0; double G_MaxLotSize=0; double G_LotStep=0; double G_Decimals=0; int G_AcctLeverage=0; int G_CurrencyLotSize=0; double G_OrderLotSize=0; int G_Count=0; int G_Slippage=5; int G_ProgStep = 0; double progSteps[15]; int maxWinPeriod = -1; int minWinPeriod = -1; int numWinPeriods = 0; double avgWinPeriod = 0; int numConsecutiveLosers = 0; int maxConsecutiveLosers = 0; int winPeriod = 0; bool lastWinner = true; int ordWinners[20]; double ordProfits[20]; double totalLoss = 0; bool initialized = false; double winPercent = 100; double wlr = 0; double avgProfit = 0; double avgLoss = 0; double expectedProfit = 0; double expectedProfitPercent = 100; double contracts = 0; double kelly = 0; int init() { initProgression(ProgressionModel); // For those of us tired of messing around assigning annoying but essential magic numbers. if (Symbol()=="AUDCADm" || Symbol()=="AUDCAD") {LongMagicNumber=100001;ShortMagicNumber=200001;} if (Symbol()=="AUDJPYm" || Symbol()=="AUDJPY") {LongMagicNumber=100002;ShortMagicNumber=200002;} if (Symbol()=="AUDNZDm" || Symbol()=="AUDNZD") {LongMagicNumber=100003;ShortMagicNumber=200003;} if (Symbol()=="AUDUSDm" || Symbol()=="AUDUSD") {LongMagicNumber=100004;ShortMagicNumber=200004;} if (Symbol()=="CHFJPYm" || Symbol()=="CHFJPY") {LongMagicNumber=100005;ShortMagicNumber=200005;} if (Symbol()=="EURAUDm" || Symbol()=="EURAUD") {LongMagicNumber=100006;ShortMagicNumber=200006;} if (Symbol()=="EURCADm" || Symbol()=="EURCAD") {LongMagicNumber=100007;ShortMagicNumber=200007;} if (Symbol()=="EURCHFm" || Symbol()=="EURCHF") {LongMagicNumber=100008;ShortMagicNumber=200008;} if (Symbol()=="EURGBPm" || Symbol()=="EURGBP") {LongMagicNumber=100009;ShortMagicNumber=200009;} if (Symbol()=="EURJPYm" || Symbol()=="EURJPY") {LongMagicNumber=100010;ShortMagicNumber=200010;} if (Symbol()=="EURUSDm" || Symbol()=="EURUSD") {LongMagicNumber=100011;ShortMagicNumber=200011;} if (Symbol()=="GBPCHFm" || Symbol()=="GBPCHF") {LongMagicNumber=100012;ShortMagicNumber=200012;} if (Symbol()=="GBPJPYm" || Symbol()=="GBPJPY") {LongMagicNumber=100013;ShortMagicNumber=200013;} if (Symbol()=="GBPUSDm" || Symbol()=="GBPUSD") {LongMagicNumber=100014;ShortMagicNumber=200014;} if (Symbol()=="NZDJPYm" || Symbol()=="NZDJPY") {LongMagicNumber=100015;ShortMagicNumber=200015;} if (Symbol()=="NZDUSDm" || Symbol()=="NZDUSD") {LongMagicNumber=100016;ShortMagicNumber=200016;} if (Symbol()=="USDCHFm" || Symbol()=="USDCHF") {LongMagicNumber=100017;ShortMagicNumber=200017;} if (Symbol()=="USDJPYm" || Symbol()=="USDJPY") {LongMagicNumber=100018;ShortMagicNumber=200018;} if (Symbol()=="USDCADm" || Symbol()=="USDCAD") {LongMagicNumber=100019;ShortMagicNumber=200019;} if (LongMagicNumber==0) {LongMagicNumber = 100999;} if (ShortMagicNumber==0) {ShortMagicNumber = 200999;} return(0); } int start() { if (!initialized) { for(int i = 0; i < 20; i++) { ordWinners[i] = 0; ordProfits[i] = 0; } initialized = true; } //====================================================== Begin Top Level Command Module ============================================================ // Global equity/risk based lot sizer G_AcctLeverage = AccountLeverage(); G_MinLotSize = MarketInfo(Symbol(),MODE_MINLOT); G_MaxLotSize = MarketInfo(Symbol(),MODE_MAXLOT); G_LotStep = MarketInfo(Symbol(),MODE_LOTSTEP); G_CurrencyLotSize = MarketInfo(Symbol(),MODE_LOTSIZE); if(G_LotStep == 0.01) {G_Decimals = 2;} if(G_LotStep == 0.1) {G_Decimals = 1;} if (UseDynamicLots) { if (G_OrderLotSize <= 0) { G_OrderLotSize = StrToDouble(DoubleToStr(LotBaseSize*AccountEquity()/LotBaseEquity,G_Decimals)); } } else { G_OrderLotSize = LotBaseSize; } if (G_OrderLotSize < G_MinLotSize) {G_OrderLotSize = G_MinLotSize;} if (G_OrderLotSize > G_MaxLotSize) {G_OrderLotSize = G_MaxLotSize;} LongGoblin(); ShortGoblin(); if (!IsTesting()) { string msg = "Avg prof "+DoubleToStr(avgProfit,2)+", avg loss "+DoubleToStr(avgLoss,2)+", w/l "+DoubleToStr(wlr,2)+ "%, prob "+DoubleToStr(winPercent,2)+"%"+ "; Exp "+DoubleToStr(expectedProfit,2)+" ("+DoubleToStr(expectedProfitPercent,2)+"%)"+ "; Kelly "+DoubleToStr(kelly,2)+", # "+DoubleToStr(contracts,2)+""; Comment("\nBUY CYCLE : Orders Open = ",L_OpenOrders," Profit = ",DoubleToStr(L_Profit,2)," +/-", "\nSELL CYCLE: Orders Open = ",S_OpenOrders," Profit = ",DoubleToStr(S_Profit,2)," +/-", "\n\n"+msg); } return(0); } //====================================================== End Of Top Level Command Module ============================================================<< void initProgression(int model) { if (model == 1) { // Increasing lot size with every winner, decrease again when losers become more likely progSteps[0] = 1; progSteps[1] = 1; progSteps[2] = 1.5; progSteps[3] = 1.5; progSteps[4] = 2; progSteps[5] = 2; progSteps[6] = 3; progSteps[7] = 3; progSteps[8] = 2; progSteps[9] = 2; progSteps[10] = 1.5; progSteps[11] = 1.5; progSteps[12] = 1; progSteps[13] = 1; } else { // Start with high factor to recover previous loss and the decrease lot size again progSteps[0] = 5; progSteps[1] = 3; progSteps[2] = 3; progSteps[3] = 2; progSteps[4] = 2; progSteps[5] = 1.5; progSteps[6] = 1.5; progSteps[7] = 1; progSteps[8] = 1; progSteps[9] = 1; progSteps[10] =1; progSteps[11] = 1; progSteps[12] = 1; progSteps[13] = 1; } } void setWinner(int orders,bool long,bool winner,double amount) { if (UseDynamicLots) { amount = amount/G_OrderLotSize; } if(UseProgression) { if (long) { amount = amount/L_ProgFactor; } else { amount = amount/S_ProgFactor; } } if (winner && orders >= 0 && orders < 20) { ordWinners[orders]++; ordProfits[orders] = ordProfits[orders]+amount; } else if (!winner) { totalLoss = totalLoss+amount; } if (long) { if (winner) { L_Winners++; } else { L_Losers++; } } else { if (winner) { S_Winners++; } else { S_Losers++; } } if (winner) { if (lastWinner) { winPeriod++; } else { winPeriod = 1; if (numConsecutiveLosers > maxConsecutiveLosers) { maxConsecutiveLosers = numConsecutiveLosers; } numConsecutiveLosers = 0; } } else { numConsecutiveLosers++; if (lastWinner) { // Run ended now if (winPeriod > maxWinPeriod) { maxWinPeriod = winPeriod; } if (winPeriod < minWinPeriod || minWinPeriod < 0) { minWinPeriod = winPeriod; } if (numWinPeriods > 0) { avgWinPeriod = (avgWinPeriod*numWinPeriods+winPeriod)/(numWinPeriods+1); numWinPeriods++; } else { avgWinPeriod = winPeriod; numWinPeriods = 1; } } else { winPeriod = 0; } } lastWinner = winner; } void LogStatistic() { int winners = L_Winners+S_Winners; int losers = L_Losers+S_Losers; double losePercent = 0; if (losers > 0) { avgLoss = totalLoss/losers; } double avgProfit1 = ordProfits[1]; if (ordWinners[1] > 0) { avgProfit1 = avgProfit1/ordWinners[1]; } double avgProfit2 = ordProfits[2]; if (ordWinners[2] > 0) { avgProfit2 = avgProfit2/ordWinners[2]; } double avgProfit3 = ordProfits[3]; if (ordWinners[3] > 0) { avgProfit3 = avgProfit3/ordWinners[3]; } double avgProfit4 = ordProfits[4]; if (ordWinners[4] > 0) { avgProfit4 = avgProfit4/ordWinners[4]; } double avgProfit5 = ordProfits[5]; if (ordWinners[5] > 0) { avgProfit5 = avgProfit5/ordWinners[5]; } double avgProfit6 = ordProfits[6]; if (ordWinners[6] > 0) { avgProfit6 = avgProfit6/ordWinners[6]; } double avgProfit7 = ordProfits[7]; if (ordWinners[7] > 0) { avgProfit7 = avgProfit7/ordWinners[7]; } double avgProfit8 = ordProfits[8]; if (ordWinners[8] > 0) { avgProfit8 = avgProfit8/ordWinners[8]; } double avgProfit9 = ordProfits[9]; if (ordWinners[9] > 0) { avgProfit9 = avgProfit9/ordWinners[9]; } double avgProfit10 = ordProfits[10]; if (ordWinners[10] > 0) { avgProfit10 = avgProfit10/ordWinners[10]; } if (winners+losers > 0) { winPercent = 100.0*winners/(winners+losers); losePercent = 100.0*losers/(winners+losers); for(int i = 1; i <= 10; i++) { avgProfit += ordProfits[i]; } expectedProfit = (totalLoss+avgProfit)/(winners+losers); if (winners > 0) { avgProfit = avgProfit/winners; } if (avgLoss < 0) { wlr = 100.0*avgProfit/(-avgLoss); expectedProfitPercent = 100*expectedProfit/(-avgLoss); if (wlr > 0) { kelly = KellyFactor*(winPercent/100.0-(100.0-winPercent)/wlr); } contracts = LotBaseEquity*kelly/(-avgLoss); } } Print("Buy winners "+L_Winners+",losers "+L_Losers+"; Sell winners "+S_Winners+", losers "+S_Losers+ "; Total winners "+winners+" ("+DoubleToStr(winPercent,0)+"%), losers "+losers+" ("+DoubleToStr(losePercent,0)+"%)"+ "; Longest run "+maxWinPeriod+", shortest run "+minWinPeriod+", avg run "+DoubleToStr(avgWinPeriod,1)+ ", max cons. losers "+maxConsecutiveLosers); Print("Losers: "+losers+" ("+DoubleToStr(avgLoss,2)+"),"+ "Winners 1: "+ordWinners[1]+" ("+DoubleToStr(avgProfit1,2)+"), "+ "2: "+ordWinners[2]+" ("+DoubleToStr(avgProfit2,2)+"), "+ "3: "+ordWinners[3]+" ("+DoubleToStr(avgProfit3,2)+"), "+ "4: "+ordWinners[4]+" ("+DoubleToStr(avgProfit4,2)+"), "+ "5: "+ordWinners[5]+" ("+DoubleToStr(avgProfit5,2)+"), "+ "6: "+ordWinners[6]+" ("+DoubleToStr(avgProfit6,2)+"), "+ "7: "+ordWinners[7]+" ("+DoubleToStr(avgProfit7,2)+"), "+ "8: "+ordWinners[8]+" ("+DoubleToStr(avgProfit8,2)+"), "+ "9: "+ordWinners[9]+" ("+DoubleToStr(avgProfit9,2)+"), "+ "10: "+ordWinners[10]+" ("+DoubleToStr(avgProfit10,2)+")"); Print("Avg profit "+DoubleToStr(avgProfit,2)+", avg loss "+DoubleToStr(avgLoss,2)+", w/l "+DoubleToStr(wlr,2)+ "%, win prob "+DoubleToStr(winPercent,2)+"%"+ "; Exp "+DoubleToStr(expectedProfit,2)+" ("+DoubleToStr(expectedProfitPercent,2)+"%)"+ "; Kelly "+DoubleToStr(kelly,2)+", # "+DoubleToStr(contracts,2)+""); } //====================================================== Begin Buy Order Processing SubRoutine ======================================================<< void LongGoblin() { L_Profit=0; L_OpenOrders=0; if (L_Balance <= 0) { L_Balance = AccountBalance(); } if (S_PreviousOpenOrders < 1) { L_AccumulatedProfit = 0; } for(L_Count=0;L_Count<OrdersTotal();L_Count++) { OrderSelect(L_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == LongMagicNumber) {L_OpenOrders++;L_Profit=L_Profit+OrderProfit();} } L_PipValue = MarketInfo(Symbol(),MODE_TICKVALUE); if (L_PipValue==0) { L_PipValue=5; } if (L_PreviousOpenOrders>L_OpenOrders) { for(L_Count=OrdersTotal();L_Count>=0;L_Count--) { OrderSelect(L_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == LongMagicNumber && OrderType() == OP_BUY) { int m_Ticket = OrderTicket(); OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),L_Slippage,Blue); Print("Closing Buy Order ",m_Ticket); return(0); } } L_OldProfit = AccountBalance()-L_Balance-S_AccumulatedProfit; if (S_AccumulatedProfit > 0) { Print("Subtracting accumulated sell profit "+S_AccumulatedProfit); } if (S_PreviousOpenOrders > 0) { L_AccumulatedProfit += L_OldProfit; } else { L_AccumulatedProfit = 0; } if (MaxProgStep > 12) { MaxProgStep = 12; } if (UseGlobalProg) { L_ProgStep = G_ProgStep; } if (L_OldProfit < LoserLimit*G_OrderLotSize) { // Loser setWinner(L_PreviousOpenOrders,true,false,L_OldProfit); L_ProgStep = 0; } else { // Winner setWinner(L_PreviousOpenOrders,true,true,L_OldProfit); L_ProgStep = L_ProgStep+1; if (L_ProgStep > MaxProgStep) { L_ProgStep = MaxProgStep; if (UseCycleProgSteps) { L_ProgStep = 0; } } } if (UseGlobalProg) { G_ProgStep = L_ProgStep; S_ProgFactor = progSteps[G_ProgStep]; } L_ProgFactor = progSteps[L_ProgStep]; if (L_ProgFactor <= 0) { L_ProgFactor = 1; } if (UseProgression) { if (L_OldProfit < LoserLimit*G_OrderLotSize) { Print("Last buy trade was a loser, factor is now "+L_ProgFactor+" (step "+L_ProgStep+")"); } else { Print("Last buy trade was a winner, factor is now "+L_ProgFactor+" (step "+L_ProgStep+")"); } } LogStatistic(); } L_PreviousOpenOrders=L_OpenOrders; if (L_OpenOrders>=LongMaxTrades) { L_ContinueOpening=False; } else { L_ContinueOpening=True; } if (L_LastPrice==0) { for(L_Count=0;L_Count<OrdersTotal();L_Count++) { OrderSelect(L_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == LongMagicNumber && OrderType() == OP_BUY) { L_LastPrice=OrderOpenPrice(); L_OrderType=2; } } } if (UseDynamicLots && !L_ContinueOpening) { G_OrderLotSize = StrToDouble(DoubleToStr(LotBaseSize*AccountEquity()/LotBaseEquity,G_Decimals)); } if (L_OpenOrders<1) {L_OrderType=OpenOrdersBasedOnTrendRSX();} // Here comes the fun part we all waited for where we update those trailing stops....yippeekyeah!! for(L_Count=OrdersTotal();L_Count>=0;L_Count--) { OrderSelect(L_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol() == Symbol() && OrderMagicNumber() == LongMagicNumber && OrderType()== OP_BUY) { if (LongTrailingStop > 0 && (Bid-OrderOpenPrice()>=(LongTrailingStop+LongPips)*Point) && (OrderStopLoss()<(Bid-Point*LongTrailingStop)) ) { OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*LongTrailingStop,OrderClosePrice()+LongTakeProfit*Point+LongTrailingStop*Point,800,Yellow); return(0); } } } L_Profit=0; L_LastTicket=0; L_LastType=0; L_LastClosePrice=0; L_LastLots=0; for(L_Count=0;L_Count<OrdersTotal();L_Count++) { OrderSelect(L_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == LongMagicNumber && OrderType()==OP_BUY) { L_LastTicket=OrderTicket(); L_LastType=OP_BUY; L_LastClosePrice=OrderClosePrice(); L_LastLots=OrderLots(); L_Profit=L_Profit+OrderProfit(); } } L_OldProfit = L_Profit; if (L_OpenOrders>=(LongMaxTrades-LongOrderstoProtect) && LongAccountProtection==true) { if (L_Profit>=LongSecureProfit) { OrderClose(L_LastTicket,L_LastLots,L_LastClosePrice,L_Slippage,Yellow); L_ContinueOpening=False; return(0); } } if (L_OpenOrders > 0 && L_OpenOrders < LongMaxTrades && ((L_LastPrice-Ask)>=LongPips*Point)) { if (L_OrderType==2 && L_ContinueOpening) { //Print("Ready to open buy order at "+Ask); } else { Print("BLOCKED buy order at "+Ask); } } if (L_OrderType==2 && L_ContinueOpening && ((L_LastPrice-Ask)>=LongPips*Point || L_OpenOrders<1) ) { BuyPrice=Ask; L_LastPrice=0; if (LongTakeProfit==0) { L_tp=0; } else { L_tp=BuyPrice+LongTakeProfit*Point; } if (LongInitialStop==0) { L_sl=0; } else { L_sl=NormalizeDouble(BuyPrice-LongInitialStop*Point - (LongMaxTrades-L_OpenOrders)*LongPips*Point, Digits); } L_OrderLotSize=G_OrderLotSize; if (L_OpenOrders <= 0) { L_OrderLotSize = FixedLotsOrder1; } else if (L_OpenOrders == 1) { L_OrderLotSize = FixedLotsOrder2; } else if (L_OpenOrders == 2) { L_OrderLotSize = FixedLotsOrder3; } else if (L_OpenOrders == 3) { L_OrderLotSize = FixedLotsOrder4; } else if (L_OpenOrders == 4) { L_OrderLotSize = FixedLotsOrder5; } else if (L_OpenOrders == 5) { L_OrderLotSize = FixedLotsOrder6; } else if (L_OpenOrders == 6) { L_OrderLotSize = FixedLotsOrder7; } else if (L_OpenOrders == 7) { L_OrderLotSize = FixedLotsOrder8; } else if (L_OpenOrders == 8) { L_OrderLotSize = FixedLotsOrder9; } else if (L_OpenOrders > 8) { L_OrderLotSize = FixedLotsOrderLast; } if (UseDynamicLots) { L_OrderLotSize = G_OrderLotSize*L_OrderLotSize; } if (UseProgression) { L_OrderLotSize = L_ProgFactor*L_OrderLotSize; } L_OrderLotSize = NormalizeDouble(L_OrderLotSize,G_Decimals); if (L_OrderLotSize < G_MinLotSize) { Print("ERROR: Lot size "+L_OrderLotSize+" too small, min "+G_MinLotSize+" required"); L_OrderLotSize = G_MinLotSize; } if (L_OrderLotSize > G_MaxLotSize) { Print("ERROR: Lot size "+L_OrderLotSize+" too big, max "+G_MaxLotSize+" allowed"); L_OrderLotSize = G_MaxLotSize; } if (L_OpenOrders<1) { L_Balance = AccountBalance(); } int nextOrder = L_OpenOrders+1; Print("Open buy @"+nextOrder+" at "+DoubleToStr(L_OrderLotSize,G_Decimals)+" at "+DoubleToStr(BuyPrice,4)+" sl "+DoubleToStr(L_sl,4)+" tp "+DoubleToStr(L_tp,4)); int ticket = OrderSend(Symbol(),OP_BUY,L_OrderLotSize,BuyPrice,L_Slippage,L_sl,L_tp,"Goblin BiPolar Buy",LongMagicNumber,0,Blue); if (ticket < 0) { Print("ERROR opening buy order at "+BuyPrice); } return(0); } return(0); } //====================================================== Begin Sell Order Processing SubRoutine =====================================================<< void ShortGoblin() { S_Profit=0; S_OpenOrders=0; if (S_Balance <= 0) { S_Balance = AccountBalance(); } if (L_PreviousOpenOrders < 1) { S_AccumulatedProfit = 0; } for(S_Count=0;S_Count<OrdersTotal();S_Count++) { OrderSelect(S_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == ShortMagicNumber) {S_OpenOrders++;S_Profit=S_Profit+OrderProfit();} } S_PipValue = MarketInfo(Symbol(),MODE_TICKVALUE); if (S_PipValue==0) { S_PipValue=5; } if (S_PreviousOpenOrders>S_OpenOrders) { for(S_Count=OrdersTotal();S_Count>=0;S_Count--) { OrderSelect(S_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == ShortMagicNumber && OrderType() == OP_SELL) { int m_Ticket = OrderTicket(); OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),S_Slippage,Red); Print("Closing Sell Order ",m_Ticket); return(0); } } S_OldProfit = AccountBalance()-S_Balance-L_AccumulatedProfit; if (L_AccumulatedProfit > 0) { Print("Subtracting accumulated buy profit "+L_AccumulatedProfit); } if (L_PreviousOpenOrders > 0) { S_AccumulatedProfit += S_OldProfit; } else { S_AccumulatedProfit = 0; } if (MaxProgStep > 12) { MaxProgStep = 12; } if (UseGlobalProg) { S_ProgStep = G_ProgStep; } if (S_OldProfit < LoserLimit*G_OrderLotSize) { // Loser setWinner(S_PreviousOpenOrders,false,false,S_OldProfit); S_ProgStep = 0; } else { // Winner setWinner(S_PreviousOpenOrders,false,true,S_OldProfit); S_ProgStep = S_ProgStep+1; if (S_ProgStep > MaxProgStep) { S_ProgStep = MaxProgStep; if (UseCycleProgSteps) { S_ProgStep = 0; } } } if (UseGlobalProg) { G_ProgStep = S_ProgStep; L_ProgFactor = progSteps[G_ProgStep]; } S_ProgFactor = progSteps[S_ProgStep]; if (S_ProgFactor <= 0) { S_ProgFactor = 1; } if (UseProgression) { if (S_OldProfit < LoserLimit*G_OrderLotSize) { Print("Last sell trade was a loser, factor is now "+S_ProgFactor+" (step "+S_ProgStep+")"); } else { Print("Last sell trade was a winner, factor is now "+S_ProgFactor+" (step "+S_ProgStep+")"); } } LogStatistic(); } S_PreviousOpenOrders=S_OpenOrders; if (S_OpenOrders>=ShortMaxTrades) { S_ContinueOpening=False; } else { S_ContinueOpening=True; } if (S_LastPrice==0) { for(S_Count=0;S_Count<OrdersTotal();S_Count++) { OrderSelect(S_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == ShortMagicNumber && OrderType() == OP_SELL) { S_LastPrice=OrderOpenPrice(); S_OrderType=1; } } } if (UseDynamicLots && !S_ContinueOpening) { G_OrderLotSize = StrToDouble(DoubleToStr(LotBaseSize*AccountEquity()/LotBaseEquity,G_Decimals)); } if (S_OpenOrders<1){S_OrderType=OpenOrdersBasedOnTrendRSX();} // Here comes the fun part we all waited for where we update those trailing stops....woohoo!! for(S_Count=OrdersTotal();S_Count>=0;S_Count--) { OrderSelect(S_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol() == Symbol() && OrderMagicNumber() == ShortMagicNumber && OrderType()==OP_SELL) { if (ShortTrailingStop > 0 && (OrderOpenPrice()-Ask>=(ShortTrailingStop+ShortPips)*Point) && (OrderStopLoss()>(Ask+Point*ShortTrailingStop)) ) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*ShortTrailingStop,OrderClosePrice()-ShortTakeProfit*Point-ShortTrailingStop*Point,800,Purple); return(0); } } } S_Profit=0; S_LastTicket=0; S_LastType=0; S_LastClosePrice=0; S_LastLots=0; for(S_Count=0;S_Count<OrdersTotal();S_Count++) { OrderSelect(S_Count, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol()==Symbol() && OrderMagicNumber() == ShortMagicNumber && OrderType()==OP_SELL) { S_LastTicket=OrderTicket(); S_LastType=OP_SELL; S_LastClosePrice=OrderClosePrice(); S_LastLots=OrderLots(); S_Profit=S_Profit+OrderProfit(); } } S_OldProfit = S_Profit; if (S_OpenOrders>=(ShortMaxTrades-ShortOrderstoProtect) && ShortAccountProtection==true) { if (S_Profit>=ShortSecureProfit) { OrderClose(S_LastTicket,S_LastLots,S_LastClosePrice,S_Slippage,Yellow); S_ContinueOpening=False; return(0); } } if (S_OpenOrders > 0 && S_OpenOrders < ShortMaxTrades && ((Bid-S_LastPrice)>=ShortPips*Point)) { if (S_OrderType==1 && S_ContinueOpening) { //Print("Ready to open sell order at "+Bid); } else { Print("BLOCKED sell order at "+Bid); } } if (S_OrderType==1 && S_ContinueOpening && ((Bid-S_LastPrice)>=ShortPips*Point || S_OpenOrders<1)) { SellPrice=Bid; S_LastPrice=0; if (ShortTakeProfit==0) { S_tp=0; } else { S_tp=SellPrice-ShortTakeProfit*Point; } if (ShortInitialStop==0) { S_sl=0; } else { S_sl=NormalizeDouble(SellPrice+ShortInitialStop*Point + (ShortMaxTrades-S_OpenOrders)* ShortPips*Point, Digits); } S_OrderLotSize=G_OrderLotSize; if (S_OpenOrders <= 0) { S_OrderLotSize = FixedLotsOrder1; } else if (S_OpenOrders == 1) { S_OrderLotSize = FixedLotsOrder2; } else if (S_OpenOrders == 2) { S_OrderLotSize = FixedLotsOrder3; } else if (S_OpenOrders == 3) { S_OrderLotSize = FixedLotsOrder4; } else if (S_OpenOrders == 4) { S_OrderLotSize = FixedLotsOrder5; } else if (S_OpenOrders == 5) { S_OrderLotSize = FixedLotsOrder6; } else if (S_OpenOrders == 6) { S_OrderLotSize = FixedLotsOrder7; } else if (S_OpenOrders == 7) { S_OrderLotSize = FixedLotsOrder8; } else if (S_OpenOrders == 8) { S_OrderLotSize = FixedLotsOrder9; } else if (S_OpenOrders > 8) { S_OrderLotSize = FixedLotsOrderLast; } if (UseDynamicLots) { S_OrderLotSize = G_OrderLotSize*S_OrderLotSize; } if (UseProgression) { S_OrderLotSize = S_ProgFactor*S_OrderLotSize; } S_OrderLotSize = NormalizeDouble(S_OrderLotSize,G_Decimals); if (S_OrderLotSize < G_MinLotSize) { Print("ERROR: Lot size "+S_OrderLotSize+" too small, min "+G_MinLotSize+" required"); S_OrderLotSize = G_MinLotSize; } if (S_OrderLotSize > G_MaxLotSize) { Print("ERROR: Lot size "+S_OrderLotSize+" too big, max "+G_MaxLotSize+" allowed"); S_OrderLotSize = G_MaxLotSize; } if (S_OpenOrders<1) { S_Balance = AccountBalance(); } int nextOrder = S_OpenOrders+1; Print("Open sell @"+nextOrder+" of "+DoubleToStr(S_OrderLotSize,G_Decimals)+" at "+DoubleToStr(SellPrice,4)+" sl "+DoubleToStr(S_sl,4)+" tp "+DoubleToStr(S_tp,4)); int ticket = OrderSend(Symbol(),OP_SELL,S_OrderLotSize,SellPrice,S_Slippage,S_sl,S_tp,"Goblin Bipolar Sell",ShortMagicNumber,0,Red); if (ticket < 0) { Print("ERROR opening sell order at "+SellPrice); } return(0); } return(0); } int deinit() { return(0); } //==================================================== And here's the lovely Buy/Sell Signal Generator ============================================<< int OpenOrdersBasedOnTrendRSX() { int SignalOrderType=3; double slowsma=0,mediumsma=0,fastsma=0; // Let's check our very reliable super secret mega-signal... if (UseJMATrend) { double jma1=iCustom(Symbol(),Period(),"Turbo_JMA",JMAPeriod,-100,0,JMALag); double jma2=iCustom(Symbol(),Period(),"Turbo_JMA",JMAPeriod,-100,0,JMALag+1); if (MathAbs(jma1 - jma2) / Point > JMAPointDiff) { if (jma1 < jma2) {SignalOrderType=1;} if (jma1 > jma2) {SignalOrderType=2;} } } // Welp, our mega-signal says no cigar...let's see what trusty 'ol RSX has to say... if (SignalOrderType==3 && UseRSX) { double UpTrendVal = iCustom(Symbol(),Period(), "Turbo_JVEL",17,-100,0,1); double DnTrendVal = iCustom(Symbol(),Period(), "Turbo_JVEL",17,-100,1,1); double TrendVal = (UpTrendVal + DnTrendVal); double rsxcurr = iCustom(Symbol(),RSX_Timeframe,"Turbo_JRSX",RSX_Period,0,1); double rsxprev1 = iCustom(Symbol(),RSX_Timeframe,"Turbo_JRSX",RSX_Period,0,2); double rsxprev2 = iCustom(Symbol(),RSX_Timeframe,"Turbo_JRSX",RSX_Period,0,3); if (UseConservativeRSX_Signals==true) { if (rsxcurr < rsxprev1 && rsxcurr < 70 && rsxprev1 > 70 && TrendVal < (-0.01)) {SignalOrderType=1;} // we only go short on RSX downturns if (rsxcurr > rsxprev1 && rsxcurr > 30 && rsxprev1 < 30 && TrendVal > (0.01)) {SignalOrderType=2;} // we only go long on RSX upturns } if (UseConservativeRSX_Signals==false) { if (rsxcurr < rsxprev1 && TrendVal < (-0.01)) {SignalOrderType=1;} // we only go short on RSX downturns if (rsxcurr > rsxprev1 && TrendVal > (0.01)) {SignalOrderType=2;} // we only go long on RSX upturns } } if (SignalOrderType == 1 && UseSMATrendFilter == true) { fastsma = iCustom(Symbol(),TrendFilterSMATimeFrame,"Turbo_JMA",TrendFilterFastSMAPeriod,-100,0,1); mediumsma = iCustom(Symbol(),TrendFilterSMATimeFrame,"Turbo_JMA",TrendFilterMediumSMAPeriod,-100,0,1); slowsma = iCustom(Symbol(),TrendFilterSMATimeFrame,"Turbo_JMA",TrendFilterSlowSMAPeriod,-100,0,1); if (slowsma > mediumsma && mediumsma > fastsma) { SignalOrderType = 1; } else { SignalOrderType = 3; } } if (SignalOrderType == 2 && UseSMATrendFilter == true) { fastsma = iCustom(Symbol(),TrendFilterSMATimeFrame,"Turbo_JMA",TrendFilterFastSMAPeriod,-100,0,1); mediumsma = iCustom(Symbol(),TrendFilterSMATimeFrame,"Turbo_JMA",TrendFilterMediumSMAPeriod,-100,0,1); slowsma = iCustom(Symbol(),TrendFilterSMATimeFrame,"Turbo_JMA",TrendFilterSlowSMAPeriod,-100,0,1); if (slowsma < mediumsma && mediumsma < fastsma) { SignalOrderType = 2; } else { SignalOrderType = 3; } } return(SignalOrderType); }
Sample
Analysis
Market Information Used:
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Turbo_JVEL
Turbo_JRSX
Turbo_JMA
Order Management characteristics:
Checks for the total of open orders
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy
It automatically opens orders when conditions are reached
Other Features: