//+------------------------------------------------------------------+ // SchaffTrendCycle.mq5 | //| Copyright © 2011, EarnForex.com | //| http://www.earnforex.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2011, EarnForex.com" #property link "http://www.earnforex.com" #property version "1.0" #property description "Schaff Trend Cycle - Cyclical Stoch over Stoch over MACD." #property description "Falling below 75 is a sell signal." #property description "Rising above 25 is a buy signal." #property description "Developed by Doug Schaff." #property description "Code adapted from the original TradeStation EasyLanguage version." #property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 1 #property indicator_minimum 0 #property indicator_maximum 100 #property indicator_level1 25 #property indicator_level2 75 #property indicator_width1 2 #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_SOLID #property indicator_color1 DarkOrchid #property indicator_label1 "STC" //---- Input Parameters input int MAShort = 23; input int MALong = 50; input int Cycle = 10; //---- Global Variables double Factor = 0.5; int BarsRequired; //---- Buffers double MACD[]; double ST[]; double ST2[]; //---- MA Buffers double MAShortBuf[]; double MALongBuf[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { IndicatorSetString(INDICATOR_SHORTNAME, "STC(" + IntegerToString(MAShort) + ", " + IntegerToString(MALong) + ", " + IntegerToString(Cycle) + ")"); SetIndexBuffer(0, ST2, INDICATOR_DATA); SetIndexBuffer(1, ST, INDICATOR_CALCULATIONS); SetIndexBuffer(2, MACD, INDICATOR_CALCULATIONS); BarsRequired = MALong + Cycle * 2; } //+------------------------------------------------------------------+ //| Schaff Trend Cycle | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if (rates_total <= BarsRequired) return(rates_total); int counted_bars = prev_calculated; double LLV, HHV; int shift, n = 1, i, myMA; // Static variables are used to flag that we already have calculated curves from the previous indicator run static bool st1_pass = false; static bool st2_pass = false; int st1_count = 0; bool check_st1 = false, check_st2 = false; if (counted_bars < BarsRequired) { for (i = 0; i < BarsRequired; i++) ST2[i] = 0; for (i = 0; i < BarsRequired; i++) ST[i] = 0; } if (counted_bars > 0) counted_bars--; shift = counted_bars - BarsRequired + MALong - 1; if (shift < 0) shift = 0; myMA = iMA(NULL, 0, MAShort, 0, MODE_EMA, PRICE_CLOSE); if (CopyBuffer(myMA, 0, 0, rates_total, MAShortBuf) != rates_total) return(0); myMA = iMA(NULL, 0, MALong, 0, MODE_EMA, PRICE_CLOSE); if (CopyBuffer(myMA, 0, 0, rates_total, MALongBuf) != rates_total) return(0); while (shift < rates_total) { MACD[shift] = MAShortBuf[shift] - MALongBuf[shift]; if (n >= Cycle) check_st1 = true; else n++; if (check_st1) { // Finding Max and Min on Cycle of MA differrences (MACD) for (i = 0; i < Cycle; i++) { if (i == 0) { LLV = MACD[shift - i]; HHV = MACD[shift - i]; } else { if (LLV > MACD[shift - i]) LLV = MACD[shift - i]; if (HHV < MACD[shift - i]) HHV = MACD[shift - i]; } } // Calculating first Stochastic if (HHV - LLV != 0) ST[shift] = ((MACD[shift] - LLV) / (HHV - LLV)) * 100; else {ST[shift] = ST[shift - 1];} // Smoothing first Stochastic if (st1_pass) ST[shift] = Factor * (ST[shift] - ST[shift - 1]) + ST[shift - 1]; st1_pass = true; // Have enough elements of first Stochastic to proceed to second if (st1_count >= Cycle) check_st2 = true; else st1_count++; if (check_st2) { // Finding Max and Min on Cycle of first smoothed Stoch for (i = 0; i < Cycle; i++) { if (i == 0) { LLV = ST[shift - i]; HHV = ST[shift - i]; } else { if (LLV > ST[shift - i]) LLV = ST[shift - i]; if (HHV < ST[shift - i]) HHV = ST[shift - i]; } } // Calculating second Stochastic if (HHV - LLV != 0) ST2[shift] = ((ST[shift] - LLV) / (HHV - LLV)) * 100; else {ST2[shift] = ST2[shift - 1];} // Smoothing second Stochastic if (st2_pass) ST2[shift] = Factor * (ST2[shift] - ST2[shift - 1]) + ST2[shift - 1]; st2_pass = true; } } shift++; } return(rates_total); } //+----------------------------------------------------