Trade FOREX with FXCM

  • Award-Winning Platform
  • 24/7 Customer Support
  • Trade Directly on Charts
  • Free $50K Practice Account

Results 1 to 7 of 7
  1. #1
    autoforexer's Avatar
    autoforexer is offline Member
    Join Date
    Jun 2010

    TTM Squeeze indicator


    I was wondering whether someone would be willing to look at the TTM indicator and try re-coding in C#. I use this indicator in thinkorswim in combination with heikin ashi charts (see attached image). I can't exactly remember where I found this code in thinkscript, but I attach it below with thinkscript help in comments.


    #declare lower Places a study on the lower subgraph.
    declare lower;
    input Length = 20;
    input price = close;
    #def <variable_name>=<expression> or def <variable_name> defines a 
    #variable you would like to work with.
    #Highest(IDataHolder data, int length) returns the highest value of 
    #data for the last length bars, Lowest(IDataHolder data, int length) 
    #returns the lowest value of data for the last length bars, and 
    #Average(IDataHolder data, int length) returns the average value of a 
    #set of data for the last length bars
    def e1 = (Highest(High, length) + Lowest(low, length)) / 2 + Average(close, length);
    #Inertia(IDataHolder data, int length) draws the linear regression 
    #curve using the least-squares method to approximate data for each 
    #set of bars defined by the length parameter. The resulting 
    #interpolation function for each set of bars is defined by the y = 
    #a * current_bar + b equation.
    def osc = Inertia(price - e1 / 2, length);
    #plot <plot_name>=<expression> or plot <plot_name> renders the data 
    #you are working with on the chart.
    plot oscp = osc;
    #reference <StudyName>(parameter1=value1,.., 
    #parameterN=valueN&thinsp).<PlotName> references a plot from another 
    def diff = reference bollingerbandsema(length = 20)."upperband" - reference KeltnerChannels."Upper_Band";
    plot mid = 0;
    #AssignValueColor(CustomColor color) paints intervals of a plot with 
    #desired colors depending on a condition.
    mid.assignValueColor(if diff >= 0 then Color.UPTICK else Color.DOWNTICK);
    #oscp.assignValueColor(if osc[1] < osc[0] then Color.CYAN else Color.magenta);
    oscp.assignValueColor(if osc[1] < osc[0] then
    if osc[0] >= 0 then
    createColor(0, 255, 255) else
    createColor(204, 0, 204)
    else if osc[0] >= 0 then
    createColor(0, 155, 155) else
    createColor(255, 155, 255));
    #SetPaintingStrategy(int paintingStrategy, double ignore user 
    #settings) controls a painting style of a line.
    รูป รูป  

  2. #2
    Bareknuckle's Avatar
    Bareknuckle is offline Member
    Join Date
    Nov 2009
    Okay, I think I got this for ya. Inertia in thinkscript from the best I could search out looks to simply be a linear regression curve according to: Inertia ? The thinkScript Reference so I treated it as such. TTM makes use of the word Momentum but I think they are simply referring to the action of the histogram throughout the calculation. I don't have anything to compare it to but based on the code you provided this should be the same. If not let me know so we can correct it. I also didn't clean up or comment my code so this may be a little dirty. Let me know if it works as it should and I will modify the code with comments, extra inputs, and what not.

    File->New->Indicator-> Name = Squeeze
    using System;
    using System.Drawing;
    using Broker.StrategyLanguage.Function.BuiltIn;
    using Fx2GoCommon;
    namespace Broker.StrategyLanguage.Indicator{
    	public class Squeeze : BaseIndicator {
    		public Squeeze(object _ctx):base(_ctx){}
    		// holds our length value, the # of std deviations for bband upper band, and # of atr's for keltner upper band
    		private int n_len = 20, n_sdev = 2;
    		private double n_atrs = 1.5;
    		[Input] public int length { get { return n_len; } set { n_len = value; } } // accessor for our length value, allows user to set length from format dialog
    		[Input] public int deviations { get { return n_sdev; } set { n_sdev = value; } }
    		[Input] public double atrs { get { return n_atrs; } set { n_atrs = value; } }
    		// simple string for a help line
    		private string _help1 = "deviations = # of deviations for BollingerBands. atrs = # of ATRs for KeltnerChannel. these help decide enter mode for mid line.";
    		[Input] public string help1 { get { return _help1; } set { } }
    		// holds current and historical values for each calculation
    		private SeriesVar<Double> high_price, low_price, avg_price, e1, osc, diff, u_bband, u_kchan, inertia_price;
    		private ISeries<Double> c_price; // holds our close price
    		private ISeries<Double> price { get { return c_price; } } // accessor to the close price
    		// functions we will be using
    		private LinearRegValue inertia;
    		private Highest hhv;
    		private Lowest llv;
    		private StandardDev bband;
    		private AvgTrueRange kchan;
    		private Average avg;
    		// plots we will be using
    		private IPlot p_osc, p_diff;
    		protected override void Construct() {
    			// creates our SeriesVar's so we can make use of them
    			high_price = new SeriesVar<Double>(this);
    			low_price = new SeriesVar<Double>(this);
    			avg_price = new SeriesVar<Double>(this);
    			e1 = new SeriesVar<Double>(this);
    			osc = new SeriesVar<Double>(this);
    			diff = new SeriesVar<Double>(this);
    			u_bband = new SeriesVar<Double>(this);
    			u_kchan = new SeriesVar<Double>(this);
    			inertia_price = new SeriesVar<Double>(this);
    			// creates our functions so we can make use of them
    			inertia = new LinearRegValue(this);
    			hhv = new Highest(this);
    			llv = new Lowest(this);
    			bband = new StandardDev(this);
    			kchan = new AvgTrueRange(this);
    			avg = new Average(this);
    			// creates our plots for the histogram and mid line, color isn't important as we set it dynamically later
    			p_osc = AddPlot(new PlotInfo("Osc", PlotType.Histogram, Color.Blue, Color.Empty, 2, 0, true));
    			p_diff = AddPlot(new PlotInfo("Mid", PlotType.Point, Color.Gray, Color.Empty, 3, 0, true));
    		protected override void Initialize() {
    			c_price = Bars.Close; // sets price to the data we want so we can use the price accessor to get to it from elsewhere
    			//-- Linear Regression Curve
    			inertia.price = inertia_price; // TTM Squeeze calls for LinRegC of the the (Close - E1) / 2. The SeriesVar inertia_price holds that calculation.
    			inertia.length = new Serie---pression<Int32>(delegate { return length; });
    			inertia.tgtbar = new ConstantExpression<Int32>(0); // Always want to look back from the current bar
    			//-- Highest High
    			hhv.price = Bars.High;
    			hhv.length = new Serie---pression<Int32>(delegate { return length; });
    			//-- Lowest Low
    			llv.price = Bars.Low;
    			llv.length = new Serie---pression<Int32>(delegate { return length; });
    			//-- Bollinger Band(Standard Deviation)
    			bband.price = price; // Bars.Close
    			bband.datatype = new ConstantExpression<Double>(1);
    			bband.length = new Serie---pression<Int32>(delegate { return length; });
    			//-- Keltner Channel(Average True Range)
    			kchan.length = new Serie---pression<Int32>(delegate { return length; });
    			//-- Average
    			avg.price = price; // Bars.Close
    			avg.length = new Serie---pression<Int32>(delegate { return length; });
    			//-- Default Values, helps to avoid null value errors
    			high_price.DefaultValue = 0; low_price.DefaultValue = 0; avg_price.DefaultValue = 0;
    			inertia_price.DefaultValue = 0; e1.DefaultValue = 0; osc.DefaultValue = 0;
    			u_bband.DefaultValue = 0; u_kchan.DefaultValue = 0; diff.DefaultValue = 0;
    		protected override void Execute() {
    			// TTM Squeeze says: def e1 = (Highest(High, length) + Lowest(low, length)) / 2 + Average(close, length);
    			// grab our current highest high, lowest low, and the average in the length specified
    			high_price.Value = hhv[0]; low_price.Value = llv[0]; avg_price.Value = avg[0];
    			// perform the calculation and store the result
    			e1.Value = (high_price.Value + low_price.Value) / 2 + avg_price.Value;
    			// TTM Squeeze says: def osc = Inertia(price - e1 / 2, length);
    			// calculate the value to the formulation osc wants and then save the result of applying LinReg to it
    			inertia_price.Value = price.Value - e1.Value / 2;
    			osc.Value = inertia[0];
    			// TTM Squeeze calls for BollingerBand.UpperBand - KeltnerChannel.UpperBand
    			// Since the upper band of each is a positive Standard Deviation or Average True Range
    			// we apply the calculation and add that to the average then get the difference between the two
    			u_bband.Value = (avg_price.Value + (deviations * bband[0]));
    			u_kchan.Value = (avg_price.Value + (atrs * kchan[0]));
    			diff.Value = u_bband.Value - u_kchan.Value;
    			// Dots on the mid line.  Mid line is always 0.  Determined by the difference between the BBand UpperBand and Keltner UpperBand
    			if (diff.Value >= 0) {
    				p_diff.Set(0, Color.Lime);
    			else {
    				p_diff.Set(0, Color.Red);
    			// Histogram.  Determined by the LinRegC of Close - E1 / 2 where E1 = (high + low) / 2 + average.
    			if (osc[1] < osc[0]) {
    				if (osc.Value >= 0) {
    					p_osc.Set(osc.Value, Color.FromArgb(0, 255, 255));
    				else {
    					p_osc.Set(osc.Value, Color.FromArgb(204, 0, 204));
    			else if (osc.Value >= 0) {
    				p_osc.Set(osc.Value, Color.FromArgb(0, 155, 155));
    			else {
    				p_osc.Set(osc.Value, Color.FromArgb(255, 155, 255));
    รูป รูป  
    Last edited by Bareknuckle; 08-30-2010 at 02:26 PM. Reason: Added some comments/updated code

  3. #3
    autoforexer's Avatar
    autoforexer is offline Member
    Join Date
    Jun 2010

    Thumbs up

    Bareknuckle, you never cease to amaze me. I still have to study your code in more detail, but it looks like you hit it right on the spot. See attached image--there are minor differences between TOS and ST but this could be a result of the different data feeds (note that there is an interesting gap in the ST data feed at around midnight 8/20 that isn't in the TOS data feed, hmm).

    To confirm your other assumptions, yes, Inertia is TOS's version of linear regression curve. In fact, looking at TOS's code for linear regression curve, it is simply Inertia(price[-displace], length). I believe TTM does indeed use the term "momentum" to mean which direction the histogram is headed.

    I think that most of your code is straightforward to follow, but addition of comments would be much appreciated anyway. I for one am still trying to figure out the usage of types involving series.

    With much gratitude,

    รูปขนาดเล็ก รูปขนาดเล็ก TTM Squeeze indicator-ttm_tos_vs_st.jpg  

    Last edited by autoforexer; 08-30-2010 at 01:26 AM. Reason: Added image

  4. #4
    autoforexer's Avatar
    autoforexer is offline Member
    Join Date
    Jun 2010
    Quote Originally Posted by autoforexer View Post
    (note that there is an interesting gap in the ST data feed at around midnight 8/20 that isn't in the TOS data feed, hmm)
    Taking a closer look, ST's data in my AUDUSD hour chart jumps from 8/20 at midnight to 8/20 at 8:00 AM and is therefore missing 7 bars. Reloading doesn't help.


  5. #5
    Bareknuckle's Avatar
    Bareknuckle is offline Member
    Join Date
    Nov 2009
    Quote Originally Posted by autoforexer View Post
    Taking a closer look, ST's data in my AUDUSD hour chart jumps from 8/20 at midnight to 8/20 at 8:00 AM and is therefore missing 7 bars. Reloading doesn't help.

    I had that happen once. Would be nice if we could force a backfill and reload data from the servers. What I did was for the pair in question when it happened to me was to first close ST and give it a few minutes to unload everything and do its saving. I then opened quote manager and for the pair in question I cleared the cache and deleted the data then closed QM and went back into ST. When it backfilled it filled the gap data. ST must be completely shutdown for this to have any affect otherwise I believe it just holds on to the data in memory.

    As for the little variance, that could be due to variance between feeds, gaps and spikes will definitely cause a short term variance. I'll get my code commented and cleaned up for you so you can see whats going on. If you could though, would you post a chart with BollingerBands, Keltner Channel, and a Linear Regression curve on both charts for a comparison of the underlying indicators.

    Added some comments to the code, should help clear up whats going on for you and added 2 extra inputs, one for # deviations and one for # atr's. These will adjust the green/red dots on the mid-line if you want to try and tweak it. Everything else is dependent on a "universal" length value so I didn't see a reason to try and stub in more so we can maintain continuity of the intended use/function of the indicator.
    Last edited by Bareknuckle; 08-30-2010 at 02:25 PM. Reason: Update

  6. #6
    autoforexer's Avatar
    autoforexer is offline Member
    Join Date
    Jun 2010
    Hi Bareknuckle,

    Thank you for the updates to the code--your comments are perfect for a C# novice like myself and the extra inputs are yummy icing on the cake.

    Sorry, I meant to include the channels on the screenshots the first time around; here they are.

    Your suggestion to exit ST and clear the cache and data in QM did the trick, filling in the missing bars. I too wish that the reload would take care of this without having to quit ST.

    รูปขนาดเล็ก รูปขนาดเล็ก TTM Squeeze indicator-st_vs_tos_2.jpg  

  7. #7
    pdfx is offline Member
    Join Date
    Dec 2009
    Hi Bareknuckle,

    Thanks a lot for the code. I am a newbie to c# and am facing issues compiling the code. The compiler gives me following errors:

    A new expression requires () or [] after type "Squeeze" [Indicator] Ln 67

    for the line:

    hhv.length = new Serie---pression<Int32>(delegate { return length; });

    It gives same error for other similar lines as well.

    Please help me to resolve this.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
Disclaimer: Trading foreign exchange on margin carries a high level of risk, and may not be suitable for all investors. The high degree of leverage can work against you as well as for you. Before deciding to trade foreign exchange you should carefully consider your investment objectives, level of experience, and risk appetite. The possibility exists that you could sustain a loss of some or all of your initial investment and therefore you should not invest money that you cannot afford to lose. You should be aware of all the risks associated with foreign exchange trading, and seek advice from an independent financial advisor if you have any doubts. Any opinions, news, research, analyses, prices, or other information contained on this website is provided as general market commentary and does not constitute investment advice. Forex Capital Markets LLC. will not accept liability for any loss or damage, including without limitation to, any loss of profit, which may arise directly or indirectly from use of or reliance on such information.