// 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_CountL_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=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=(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_CountS_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=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=(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); }