/*[[ Name := TSD Author := Copyright © 2005 Bob O'Brien / Barcode Link := Notes := Based on Alexander Elder's Triple Screen system. To be run only on a daily chart. Lots := 1.00 Stop Loss := 0 Take Profit := 100 Trailing Stop := 60 ]]*/ /* This expert uses the original logic from Bob o'Brians TSD V1.1. Weekly direction is determined by OSMA and daily direction is determined by Force. Follow Bob's instruction documents for the installation and use of this expert. Changes To Original Expert 1) MM section was replaced with position sizing section that calculates lot sizing based on the percentage of account balance user wishes to risk on each trade. The risk is defined as the distance from entry to stoploss in pips multiplied by the pip value. The user sets the percentage on the setup window with Defines: Trade_Risk. This version rounds up lot size, change to suit your preferences. Example: If account balance is $50,000 and you wish to risk 1% per trade and the stoploss is 100 pips then (assuming pip value of $10.00) lots = (50,000*0.01)/(100*10) = 0.5 lots. Valid lot sizes are 0.1 to 50 in 0.1 lot increments. This works with live and demo accounts on FXDD, other brokers may be different. 2) Modify order section was replaced by delete and reset order to obtain proper position sizing with the changed entry and stoploss values. As the distance between entry and stoploss can change by a large amount when a pending stop order is modified, you can end up with a position size either much larger or much smaller than you desire. Instead of ModifyOrder, DeleteOrder is used and a flag is set to allow the expert to recalculate the correct position size and reset the pending stop order with the new parameters 3) Testing added to help ensure opening & closing of orders is performed. This simply sets a flag and gets a timestamp when attempting an order operation. It allows the expert to wait up to three 10 second intervals if needed to ensure that the flagged operation was a success. If the operation was not successful an alert will appear and the expert will resubmit the order operation. Although very simple, this has saved & earned a lot of money over the past year when an expert either did not submit the operation to the server or the server did not respond. To disable the screen alert, change Defines: Screen_Alerts(1) to (0) 4) A simple weekly & daily direction comment was added 5) Collision avoidance was changed to trade 9 pairs. Replace with the original collision code if you wish to trade only 4 pairs 6) Spread was added to entry price. Order entry is + spread + 1 of high or - spread -1 of low. Change to suit your preferences. 7) Print statements were added to check operation. These extra print statements can be commented out to keep the journal cleaner. Please report any improvements, fixes, etc to MetaTrader_Experts_and_Indicators@yahoogroups.com FXFlash52 */ Defines: Slippage(5); // Slippage Var: StopYear(2005); var: PriceOpen(0); // Price Open var: I(0); // Misc Counter Var: NewBar(0),First(True); Var: Direction(0),TradesThisSymbol(0); Var: ForcePos(0), ForceNeg(0), NewPrice(0), GlobalName(""); Var: StartMinute1(0),EndMinute1(0),StartMinute2(0),EndMinute2(0),StartMinute3(0),EndMinute3(0); Var: StartMinute4(0),EndMinute4(0),StartMinute5(0),EndMinute5(0),StartMinute6(0),EndMinute6(0); var: StartMinute7(0),EndMinute7(0),DummyField(0); //---- Variables below this point added to original Defines: Trade_Risk(1); // % of acct balance risked on any 1 trade Defines: Screen_Alerts(1); // 1 is on, 0 is off Var: pip$(10),stop(100),lotsi(0),prev_lotsi(0),cnt(0),spread(0); Var: AttemptedTradeTime(0); // timestamp each time expert attempts any order operation Var: Delete_Replace(0); // flag to delete and then re-enter (modify) pending stop order //---- Variables below from Close & Open test section var: close_sell(False),close_buy(False),close_trades(0),testcount(0); var: open_short(False),open_long(False),open_trades(0); ///////////////////////////////////////////////// // Initialisation ///////////////////////////////////////////////// if year < stopyear then exit; If CurTime-LastTradeTime < 10 // if expert executed or tried to execute order operation OR CurTime-AttemptedTradeTime < 10 // then wait 10 seconds then Exit; If FreeMargin < 500 then Exit; TradesThisSymbol = 0; For I = 1 to TotalTrades { if ord(I, VAL_SYMBOL) == Symbol then TradesThisSymbol ++; }; //---- Determine Force ForcePos = iForce(2,MODE_EMA,PRICE_CLOSE,1) > 0; ForceNeg = iForce(2,MODE_EMA,PRICE_CLOSE,1) < 0; //---- Direction Comments If ForcePos Then { Comment("\n Last week's direction = ",Direction, "\n Yesterdays direction = 1"); }; If ForceNeg then { Comment("\n Last week's direction = ",Direction, "\n Yesterdays direction = -1"); }; //---- Collision Avoidance /* Select a range of minutes in the day to start trading based on the currency pair. This is to stop collisions occurring when 2 or more currencies set orders at the same time. This is set for nine currency pairs. If testing only 4 pairs then replace this section with the original expert collision code */ switch Symbol { case "USDCHF": StartMinute1 = 0; EndMinute1 = 1; StartMinute2 = 18; EndMinute2 = 19; StartMinute3 = 37; EndMinute3 = 38; StartMinute4 = 55; EndMinute4 = 56; break; case "GBPUSD": StartMinute1 = 2; EndMinute1 = 3; StartMinute2 = 21; EndMinute2 = 22; StartMinute3 = 39; EndMinute3 = 40; StartMinute4 = 57; EndMinute4 = 59; break; case "USDJPY": StartMinute1 = 4; EndMinute1 = 5; StartMinute2 = 23; EndMinute2 = 24; StartMinute3 = 41; EndMinute3 = 42; break; case "EURUSD": StartMinute1 = 6; EndMinute1 = 7; StartMinute2 = 25; EndMinute2 = 26; StartMinute3 = 43; EndMinute3 = 44; break; case "USDCAD": StartMinute1 = 8; EndMinute1 = 9; StartMinute2 = 27; EndMinute2 = 28; StartMinute3 = 45; EndMinute3 = 46; break; case "AUDUSD": StartMinute1 = 10; EndMinute1 = 11; StartMinute2 = 29; EndMinute2 = 30; StartMinute3 = 47; EndMinute3 = 48; break; case "EURJPY": StartMinute1 = 12; EndMinute1 = 13; StartMinute2 = 31; EndMinute2 = 32; StartMinute3 = 49; EndMinute3 = 50; break; case "EURGBP": StartMinute1 = 14; EndMinute1 = 15; StartMinute2 = 33; EndMinute2 = 34; StartMinute3 = 51; EndMinute3 = 52; break; case "GBPJPY": StartMinute1 = 16; EndMinute1 = 17; StartMinute2 = 35; EndMinute2 = 36; StartMinute3 = 53; EndMinute3 = 54; break; }; If (Minute >= StartMinute1 and Minute <= EndMinute1) or (Minute >= StartMinute2 and Minute <= EndMinute2) or (Minute >= StartMinute3 and Minute <= EndMinute3) or (Minute >= StartMinute4 and Minute <= EndMinute4) Then { DummyField = 0; // dummy statement because MT will not allow me to use a continue statement } Else Exit; //*********************************************************************************************** //---- Test for confirmation of close order operations //---- Close shorts test if close_sell = True // if expert tried to close a trade then { if close_trades > TradesThisSymbol // and was successful then { close_sell = False; Print("Delete sellstop successful. ",symbol); testcount = 0; close_trades = 0; exit; } else // or was unsuccessful { testcount ++; if testcount >= 3 // if after waiting 3 - 10 second intervals then { Print("Error - Attempt to delete sellstop failed. ",symbol); if screen_alerts = 1 and testcount >= 3 then { Alert("TSD Alert - Error", "\nAttempt to delete sellstop failed.", "\nTime: ",TimeToStr(curtime)," | Currency Cross: ",symbol); }; close_sell = False; // cry uncle exit; } else { AttemptedTradeTime = CurTime; // get timestamp exit; // if less than 3 waits, wait again }; }; }; //---- Close longs test if close_buy = True // if expert tried to close a trade Then { if close_trades > TradesThisSymbol // and was successful then { close_buy = False; Print("Delete buystop successful. ",symbol); testcount = 0; close_trades = 0; exit; } else // or was unsuccessful { testcount ++; if testcount >= 3 // if after waiting 3 - 10 second intervals then { Print("Error - Attempt to delete buystop failed. ",symbol); if screen_alerts = 1 and testcount >= 3 then { Alert("TSD Alert - Error", "\nAttempt to delete buystop failed.", "\nTime: ",TimeToStr(curtime)," | Currency Cross: ",symbol); }; close_buy = False; // give up exit; } else { AttemptedTradeTime = CurTime; // get timestamp exit; // if less than 3 waits, wait again }; }; }; //*********************************************************************************************** //---- Test for confirmation of open order operations //---- Test open longs if open_long = True // if expert tried to open a trade then { if open_trades < TradesThisSymbol // and was successful then { open_long = False; Delete_Replace = 0; Print("Set buystop successful. ",symbol); testcount = 0; open_trades = 0; exit; } else // or was unsuccessful { testcount ++; if testcount >= 3 // if after waiting 3 - 10 second intervals then { Print("Error - Attempt to set buystop failed. ",symbol); if screen_alerts = 1 and testcount >= 3 then { Alert("TSD Alert - Error", "\nAttempt to set buystop failed.", "\nTime: ",TimeToStr(curtime)," | Currency Cross: ",symbol); }; open_long = False; // give up exit; } else { AttemptedTradeTime = CurTime; // get timestamp exit; // if less than 3 waits, wait again }; }; }; //---- Test open shorts if open_short = True // if expert tried to open a trade then { if open_trades < TradesThisSymbol // and was successful then { open_short = False; Delete_Replace = 0; Print("Set sellstop successful. ",symbol); testcount = 0; open_trades = 0; exit; } else // or was unsuccessful { testcount ++; if testcount >= 3 // if after waiting 3 - 10 second intervals then { Print("Error - Attempt to set sellstop failed. ",symbol); if screen_alerts = 1 and testcount >= 3 then { Alert("TSD Alert - Error", "\nAttempt to set sellstop failed.", "\nTime: ",TimeToStr(curtime)," | Currency Cross: ",symbol); }; open_short = False; // give up but leave order triggers set for another attempt exit; } else { AttemptedTradeTime = CurTime; // get timestamp exit; // if less than 3 waits, wait again }; }; }; ///////////////////////////////////////////////// // Process the next bar details ///////////////////////////////////////////////// If NewBar != t[0] Or Delete_Replace != 0 Then { NewBar = t[0]; // Global Variable has a 1 if Weekly OSMA is rising and a -1 if Weekly OSMA is falling. GlobalName = "Gb1_Wk_"+Symbol+"_Direction"; Direction=GetGlobalVariable(GlobalName); Print(Symbol," Global_Direction=",Direction); If ForcePos then Print(Symbol," Daily Direction = 1"); If ForceNeg then Print(Symbol," Daily Direction = -1"); If TradesThisSymbol < 1 Then { //*********************************************************************************************** //---- Position Sizing //---- Determine pip and spread values // Trading any symbols other than the 1st seven below requires the use of either expert or indicator "Cross Rates" // to get the needed currency cross rate. Place "Cross Rates" on the chart indicated in the comment following // the desired currency pair below. "Cross Rates" sets a global variable with the required currency rate which // is read by this expert when calculating the pip value. // Tested with FXDD, other brokers may vary Switch Symbol { Case "GBPUSD": pip$= 10;//(0.0001/Bid)*100000*Bid; spread = (ask-bid); Break; Case "USDCHF": pip$=(0.0001/Bid)*100000; spread = (ask-bid); Break; Case "EURUSD": pip$= 10;//(0.0001/Bid)*100000*Bid; spread = (ask-bid); Break; Case "USDCAD": pip$=(0.0001/Bid)*100000; spread = (ask-bid); Break; Case "AUDUSD": pip$= 10;//(0.0001/Bid)*100000*Bid; spread = (ask-bid); Break; Case "USDJPY": pip$=(0.01/Bid)*100000; spread = (ask-bid); Break; Case "NZDUSD": pip$= 10;//(0.0001/bid)*100000*Bid; spread = (ask-bid); Break; Case "EURJPY": pip$=(0.01)*100000/GetGlobalVariable("USDJPY_RATE");// place expert "Cross Rates" on any USDJPY chart spread = (ask-bid); Break; Case "EURGBP": pip$=(0.0001)*100000*GetGlobalVariable("GBPUSD_RATE");// place expert "Cross Rates" on any GBPUSD chart spread = (ask-bid); Break; Case "GBPJPY": pip$=(0.01)*100000/GetGlobalVariable("USDJPY_RATE");// place expert "Cross Rates" on any USDJPY chart spread = (ask-bid); Break; Case "EURCAD": pip$=(0.0001/GetGlobalVariable("USDCAD_RATE"))*100000;// place expert "Cross Rates" on any USDCAD chart spread = (ask-bid); Break; /* Case "EURCHF": pip$=(0.0001)*100000/GetGlobalVariable("USDCHF_RATE");// place expert "Cross Rates" on any USDCHF chart spread = (ask-bid); Break; Case "CHFJPY": pip$=(0.01/GetGlobalVariable("USDJPY_RATE"))*100000;// place expert "Cross Rates" on any USDJPY chart spread = (ask-bid); Break; Case "GBPCHF": pip$=(0.0001)*100000/GetGlobalVariable("USDCHF_RATE");// place expert "Cross Rates" on any USDCHF chart spread = (ask-bid); Break; Case "EURAUD": pip$=(0.0001*GetGlobalVariable("AUDUSD_RATE"))*100000;// place expert "Cross Rates" on any AUDUSD chart spread = (ask-bid); Break; Case "AUDCAD": pip$=(0.0001/GetGlobalVariable("USDCAD_RATE"))*100000;// place expert "Cross Rates" on any USDCAD chart spread = (ask-bid); Break; Case "AUDJPY": pip$=(0.01/GetGlobalVariable("USDJPY_RATE"))*100000;// place expert "Cross Rates" on any USDJPY chart spread = (ask-bid); Break; Case "AUDNZD": pip$=(0.0001*100000)*GetGlobalVariable("NZDUSD_RATE");// place expert "Cross Rates" on any NZDUSD chart spread = (ask-bid); Break; */ Default: pip$=10; Break; }; //---- Determine Stop size in pips stop = 100; // reset stop value If (Direction = 1 and ForceNeg) OR Delete_Replace = 1 then { PriceOpen = High[1]+Spread+(1*Point); // Buy 1 point plus spread above high of previous candle If PriceOpen > (Ask + 16 * Point) Then // Check if buy price is a least 16 points > Ask { stop = (PriceOpen - Low[1] - (1 * Point))/Point; } Else { PriceOpen = Ask + 16 * Point; stop = (PriceOpen - Low[1] - (1 * Point))/Point; }; }; If (Direction = -1 and ForcePos) OR Delete_Replace = -1 then { PriceOpen = Low[1]-Spread-(1*Point); If PriceOpen < (Bid - 16 * Point) Then // Check if buy price is a least 16 points < Bid { stop = (High[1] + (1 * Point)- PriceOpen)/Point; } Else { PriceOpen = Bid - 16 * Point; stop = (High[1] + (1 * Point)- PriceOpen)/Point; }; }; //---- Calculate position size Lotsi = (Balance*(Trade_Risk/100))/(stop*pip$); if lotsi < 0.05 then lotsi = 0; if lotsi <= 50 and lotsi >= 0.05// valid values are increments of 0.1 from 0.1 up to 50 then { cnt = 0.05; while cnt < 51 { if lotsi >= cnt and lotsi < (cnt + 0.1) then { lotsi = cnt + 0.05; Break; }; cnt = cnt + 0.1; }; } else Lotsi = Round(Lotsi); if lotsi > 50 then lotsi = 50;// FXDD maximum lot size is 50 If lotsi = 0 then Print("Error: Lots = 0 ",Symbol); //---------------------------- /* //---- Prevents % risked from decreasing if balance decreases if lotsi > 0 // prevent lotsi from decreasing after a loss and lotsi < prev_lotsi then lotsi = prev_lotsi; if lotsi > prev_lotsi then prev_lotsi = lotsi;// increase prev_lotsi to highest lotsi value */ //---- End of position sizing //*********************************************************************************************** ///////////////////////////////////////////////// // New Orders Management ///////////////////////////////////////////////// // Following 2 lines moved up to position sizing section // ForcePos = iForce(2,MODE_EMA,PRICE_CLOSE,1) > 0; // ForceNeg = iForce(2,MODE_EMA,PRICE_CLOSE,1) < 0; If (Direction = 1 and ForceNeg) Or Delete_Replace = 1 then { PriceOpen = High[1]+Spread+(1*Point); // Buy 1 point plus spread above high of previous candle If PriceOpen > (Ask + 16 * Point) Then // Check if buy price is a least 16 points > Ask { Delete_Replace = 1; // set buy flag Print("Set Buystop ",symbol); open_long = True; open_trades = TradesThisSymbol; AttemptedTradeTime = CurTime; // get timestamp SetOrder(OP_BUYSTOP, lotsi, PriceOpen, Slippage, Low[1] - 1 * Point, PriceOpen + TakeProfit * Point, DodgerBlue); Exit; } Else { NewPrice = Ask + 16 * Point; Delete_Replace = 1; // set flag Print("Set Buystop ",symbol); open_long = True; open_trades = TradesThisSymbol; AttemptedTradeTime = CurTime; // get timestamp SetOrder(OP_BUYSTOP, lotsi, NewPrice, Slippage, Low[1] - 1 * Point, NewPrice + TakeProfit * Point, DodgerBlue); Exit; }; }; If (Direction = -1 and ForcePos) Or Delete_Replace = -1 then { PriceOpen = Low[1]-Spread-(1*Point);// Sell 1 point plus spread below low of previous candle If PriceOpen < (Bid - 16 * Point) Then // Check if sell price is a least 16 points < Bid { Delete_Replace = -1; // set flag Print("Set sellstop ",symbol); open_short = True; open_trades = TradesThisSymbol; AttemptedTradeTime = CurTime; // get timestamp SetOrder(OP_SELLSTOP, lotsi, PriceOpen, Slippage, High[1] + 1 * Point, PriceOpen - TakeProfit * Point, RED); Exit; } Else { NewPrice = Bid - 16 * Point; Delete_Replace = -1; // set flag Print("Set sellstop ",symbol); open_short = True; open_trades = TradesThisSymbol; AttemptedTradeTime = CurTime; // get timestamp SetOrder(OP_SELLSTOP, lotsi, NewPrice, Slippage, High[1] + 1 * Point, NewPrice - TakeProfit * Point, RED); Exit; }; }; }; ///////////////////////////////////////////////// // Pending Order Management ///////////////////////////////////////////////// If TradesThisSymbol > 0 Then { For i=1 to TotalTrades { if Ord(i,VAL_TYPE) = OP_BUYSTOP And OrderValue(i,VAL_SYMBOL) = Symbol Then // Delete non valid buystops { if Direction = -1 then { close_buy = True; close_trades = TradesThisSymbol; Print("Delete buystop. ",symbol); AttemptedTradeTime = CurTime; // get timestamp DeleteOrder(OrderValue(i,VAL_TICKET),Red); Exit; }; }; if Ord(i,VAL_TYPE) = OP_SELLSTOP And OrderValue(i,VAL_SYMBOL) = Symbol Then// Delete non valid sellstops { if Direction = 1 then { close_sell = True; close_trades = TradesThisSymbol; Print("Delete sellstop. ",symbol); AttemptedTradeTime = CurTime; // get timestamp DeleteOrder(OrderValue(i,VAL_TICKET),Red); Exit; }; }; If Ord(i,VAL_TYPE) = OP_BUYSTOP And OrderValue(i,VAL_SYMBOL) = Symbol Then { If High[1] < High[2] Then { Delete_Replace = 1; // set flag to re-open order with new lot size, price, sl,tp close_buy = True; close_trades = TradesThisSymbol; Print("Delete buystop. ",symbol); AttemptedTradeTime = CurTime; // get timestamp DeleteOrder(OrderValue(i,VAL_TICKET),Red); // delete existing pending order prior to re-opening Exit; }; }; If Ord(i,VAL_TYPE) = OP_SELLSTOP And OrderValue(i,VAL_SYMBOL) = Symbol Then { If Low[1] > Low[2] Then { Delete_Replace = -1; // set flag to re-open order with new lot size, price, sl,tp close_sell = True; close_trades = TradesThisSymbol; Print("Delete sellstop. ",symbol); AttemptedTradeTime = CurTime; // get timestamp DeleteOrder(OrderValue(i,VAL_TICKET),Red); // delete existing pending order prior to re-opening Exit; }; }; }; }; }; ///////////////////////////////////////////////// // Stop Loss Management ///////////////////////////////////////////////// If TradesThisSymbol > 0 Then { For i=1 to TotalTrades { If Ord(i,VAL_TYPE) = OP_BUY And OrderValue(i,VAL_SYMBOL) = Symbol Then { If (Ask-Ord(i,VAL_OPENPRICE)) > (TrailingStop * Point) Then { If Ord(i,VAL_STOPLOSS) < (Ask - TrailingStop * Point) Then { ModifyOrder(Ord(i,VAL_TICKET), Ord(i,VAL_OPENPRICE), Ask - TrailingStop * Point, Ask + TakeProfit * Point, White); Exit; }; }; }; If Ord(i,VAL_TYPE) = OP_SELL And OrderValue(i,VAL_SYMBOL) = Symbol Then { If (Ord(i,VAL_OPENPRICE) - Bid) > (TrailingStop * Point) Then { If Ord(i,VAL_STOPLOSS) > (Bid + TrailingStop * Point) Then { ModifyOrder(Ord(i,VAL_TICKET), Ord(i,VAL_OPENPRICE), Bid + TrailingStop * Point, Bid - TakeProfit * Point, Gold); Exit; }; }; }; }; };