Trade FOREX with FXCM

• Award-Winning Platform
• 24/7 Customer Support
• Trade Directly on Charts
• Free \$50K Practice Account
 Log in
Results 1 to 7 of 7

Thread: TTM Squeeze indicator

1. TTM Squeeze indicator

Hello,

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.

TIA,
autoforexer

Code:
```#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
#script.

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
#UpPos
createColor(0, 255, 255) else
#UpNeg
createColor(204, 0, 204)
else if osc[0] >= 0 then
#DnPos
createColor(0, 155, 155) else
#DnNeg
createColor(255, 155, 255));

#SetPaintingStrategy(int paintingStrategy, double ignore user
#settings) controls a painting style of a line.

oscp.setPaintingStrategy(PaintingStrategy.HISTOGRAM);
mid.setPaintingStrategy(PaintingStrategy.POINTS);```

2. 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
Code:
```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. 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,

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

4. Originally Posted by autoforexer
(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.

-autoforexer

5. Originally Posted by autoforexer
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.

-autoforexer
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. 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.

Best,
autoforexer

7. Member
Join Date
Dec 2009
Posts
9
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.

Thanks,

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. The possibility exists that you could sustain a loss in excess to your investment and therefore you should not invest money that you cannot afford to lose. Before deciding to trade foreign exchange you should carefully consider your investment objectives, level of experience, and risk appetite. 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. FXCM 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.