Multi-Time Frame True Momentum Oscillator (MTF) for ThinkorSwim

David45

Member
2019 Donor
Can anyone help me create a study for buy and sell signals using TMO Daily and TMO weekly crossovers? I would like to keep the study as simple as possible. The study would be for the upper chart pane and only plot arrows above and below the candlesticks when the following conditions are met:

1. When TMO daily crosses below TMO weekly AND TMO daily matches the direction of TMO weekly - a red arrow pointing down appears above the candlestick (Short).

2. When TMO daily crosses above TMO weekly AND TMO daily matches the direction of TMO weekly - a green arrow pointing up appears below the candlestick (Long).

Thanks very much in advance for any assistance with this!
 

BenTen

Administrative
Staff member
Staff
VIP
@David45 Mind posting screenshots of this idea? That would help. I'd imagine the crossover would not happen simultaneously as the weekly is longer than the daily period. I've not tested this, but if you have any instances where it matches, please add some screenshots.
 

David45

Member
2019 Donor
@David45 Mind posting screenshots of this idea? That would help. I'd imagine the crossover would not happen simultaneously as the weekly is longer than the daily period. I've not tested this, but if you have any instances where it matches, please add some screenshots.

Hi BenTen,

Thanks very much for your reply! I'm not sure how to post images so here is a post by skynetgen who kindly replied to me when I asked him how he uses TMO daily and TMO weekly crossovers for long and short signals.

https://usethinkscript.com/threads/tmo-or-rsi-in-laguerre-time-with-fe-q-a.477/post-3813

I think Mobius who created the TMO indicator also said the best way to use it was by overlaying two different aggregation periods and look for crossovers such as the TMO daily crossing above and below the TMO weekly to get long and short signals.

The crossovers seems straight forward to me, but the part that is a bit ambiguous is how to determine if the direction of the TMO daily matches the direction of the TMO weekly when the crossovers occur? Maybe @skynetgen can clarify this a bit more? It's my understanding that having the direction of both aggregation periods in unison when the crossovers occur increases the likelihood that the signals are correct and can be acted upon. I'm pretty sure @markos also uses TMO crossovers for signals so maybe he can also provide some insight as to how to determine if both aggregation periods are in directional unison at the time of the crossovers.

I am a big believer in simplicity. I like to keep my charts as clean and simple as possible. So my idea for this study was to not have it plot in the lower chart pane like the picture in netskygen's post. Instead, the study would plot in the upper chart pane. The only thing the study would plot on the chart would be up arrows below the candlestick (Long) and down arrows above the candlestick (Short) when the crossovers occur and the aggregations are in directional unison.

I cannot thank you enough BenTen for trying to help me figure this out! It is so much appreciated!
 
Last edited:

JWH

New member
VIP
I'm running what I believe to be an unadulterated version of the TMO with multiple aggregations. When I install it on a daily chart and set the aggregation to weekly, the chart starts to jerk to the left periodically. It's Sunday night, and it started doing it again. I believe it has something to do with the overnight sessions, but don't know how to prevent from happening. Any suggestions?
 

islandcowgirl

New member
VIP
Hi All,

I am mildly proficient in altering TOS code to customize it for alerts, however I have not been able to figure this one out. If anyone can help me code an alert for this when the Plot.six dot turns green for buy and red for sell that would be so awesome. I have been banging my head on this for a while and can't quite get it.

Plot.six basically plots a dot when the agg conditions line up green/buy and red/sell. (grey is neutral and doesnt need an alert)

Here is the part of the code that needs to alert. If you would need the whole code let me know...but I think you just need this part.

Code:
plot Six = if IsNaN(cl)
then Double.NaN
else 0;
Six.SetStyle(Curve.POINTS);
Six.SetLineWeight(3);
Six.AssignValueColor(if FirstAgg and
SecondAgg and
ThirdAgg and
FourthAgg and
FifthAgg
then Color.green
else if !FirstAgg and
!SecondAgg and
!ThirdAgg and
!FourthAgg and
!FifthAgg
then Color.red
else Color.light_gray);
 

BenTen

Administrative
Staff member
Staff
VIP
Add this snippet to the end of your script:

Code:
Alert(Six, " ", Alert.Bar, Sound.Chimes);

If that doesn't work, you probably going to need to post the entire script.
 

islandcowgirl

New member
VIP
Hello BenTen,

Thanks for the help! That one didn't work.
I will post the entire code below. Basically, I want a sell alert when the Six dot goes from black to red and a buy alert when it goes from black to green.

Any ideas on how to do this would be much appreciated!

Code:
#MTF True Momentum Oscillator MTF Trend Magic and MTF ATR SuperTrend
#combined enhancements by HighBredCloud
#V12.14.2019

# filename: MR__EZ_TMO_MTF_Fisher_2Agg_
# source: https://usethinkscript.com/d/91-tmo-with-higher-agg-mobius-tsl

# TMO ((T)rue (M)omentum (O)scillator) With Higher Aggregation
# Mobius
# V01.05.2018
#hint: TMO calculates momentum using the DELTA of price. Giving a much better picture of trend, trend reversals and divergence than momentum oscillators using price.

declare lower;

input length = 14; # default -> 14;
def calcLength = 5;
def smoothLength = 3;
input aggA = AggregationPeriod.FIVE_MIN;

def o = open(period = aggA);
def c = close(period = aggA);
def data = fold i = 0 to length
           with s
           do s + (if c > GetValue(o, i)
                   then 1
                   else if c < GetValue(o, i)
                        then - 1
                        else 0);
def EMA5 = ExpAverage(data, calcLength);
plot Main = ExpAverage(EMA5, smoothLength);
plot Signal = ExpAverage(Main, smoothLength);
Main.AssignValueColor(if Main > Signal
                            then Color.GREEN
                            else Color.RED);
Signal.AssignValueColor(if Main > Signal
                            then Color.GREEN
                            else Color.RED);
Main.SetLineWeight(1);
Signal.SetLineWeight(1);
Signal.HideBubble();
Signal.HideTitle();


# JQ_FisherTransform_wLabels v02
# assistance provided by AlphaInvestor, amalia, randyr and nube

# v02 9.23.2018 JQ added arrows

input Fisherprice = hl2;
input FisherLength = 10;
input TriggerLineOffset = 1; # Ehler's value of choice is 1
input TriggerLine_Color_Choice = {"magenta", "cyan", "pink", default "gray", "Mustard", "red", "green", "dark_gray", "Pale Yellow", "white"};
input deBug = no;

def maxHigh = Highest(Fisherprice, FisherLength);
def minLow = Lowest(Fisherprice, FisherLength);
def range = maxHigh - minLow;
def value = if IsNaN(Fisherprice)
then Double.NaN
else if IsNaN(range)
then value[1]
else if range == 0
then 0
else 0.66 * ((Fisherprice - minLow) / range - 0.5) + 0.67 * value[1];
def truncValue = if value > 0.99 then 0.999 else if value < -0.99 then -0.999 else value;
def fish = 0.5 * (Log((1 + truncValue) / (1 - truncValue)) + fish[1]);
def FTOneBarBack = fish[TriggerLineOffset];
def FT = fish;

plot FisherBullCross = if FT crosses above FTOneBarBack then LowestAll(Main) else Double.NaN;
FisherBullCross.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
FisherBullCross.SetDefaultColor(Color.WHITE);

plot FisherBearCross = if FT crosses below FTOneBarBack then HighestAll(Main) else Double.NaN;
FisherBearCross.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
FisherBearCross.SetDefaultColor(Color.WHITE);


input length2 = 14; # default -> 14;
def calcLength2 = 5;
def smoothLength2 = 3;
input aggB = AggregationPeriod.FIFTEEN_MIN;

def o2 = open(period = aggB);
def c2AA = close(period = aggB);
def data2 = fold i2 = 0 to length2
           with s2
           do s2 + (if c2AA > GetValue(o2, i2)
                   then 1
                   else if c2AA < GetValue(o2, i2)
                        then - 1
                        else 0);
def EMA52 = ExpAverage(data2, calcLength2);
plot Main2 = ExpAverage(EMA52, smoothLength2);
plot Signal2 = ExpAverage(Main2, smoothLength2);
Main2.AssignValueColor(if Main2 > Signal2
                            then Color.UPTICK
                            else Color.DOWNTICK);
Signal2.AssignValueColor(if Main2 > Signal2
                            then Color.UPTICK
                            else Color.DOWNTICK);
Signal2.HideBubble();
Signal2.HideTitle();

AddCloud(Main, Signal, Color.GREEN, Color.RED);
AddCloud(Main2, Signal2, Color.UPTICK, Color.DOWNTICK);

plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.MAGENTA);
ZeroLine.HideBubble();
ZeroLine.HideTitle();

plot ob = if IsNaN(c) then Double.NaN else Round(length * .7);
ob.SetDefaultColor(Color.DARK_ORANGE);
ob.HideBubble();
ob.HideTitle();
plot os = if IsNaN(c) then Double.NaN else -Round(length * .7);
os.SetDefaultColor(Color.CYAN);
os.HideBubble();
os.HideTitle();
AddCloud(ob, length, Color.DARK_ORANGE, Color.DARK_ORANGE, no);
AddCloud(-length, os, Color.CYAN, Color.CYAN);
#
# Trend Magic MTF
# tomsk
# 11.26.2019

# V1.0 - 08.08.2019 - Horserider - Added MTF to Trend Magic
# V1.1 - 11.26.2019 - tomsk      - Optimized code structure, removed duplicate variables
# V1.2 - 11.26.2019 - tomsk      - Converted this study to a lower study with MTF triangles

#declare lower;

# GLOBAL DEFINITIONS

DefineGlobalColor("TrendUp", CreateColor(0, 254, 30));
DefineGlobalColor("TrendDown", CreateColor(255, 3, 2));

input agg1TM = AggregationPeriod.FIFTEEN_MIN;
input agg2TM = AggregationPeriod.THIRTY_MIN;
input agg3TM = AggregationPeriod.HOUR;

input lengthCCI = 50;
input lengthATR = 5;
input AtrFactor = 0.7;

input DotSize = 3;
input n = 3;

def n1  = n + 1;

# AGGREGATION 1

def c1A = close(period = agg1TM);
def h1A = high(period = agg1TM);
def l1A = low(period = agg1TM);
def pricedata1A = hl2(period = agg1TM);
def ATRcci1A = Average(TrueRange(h1A, c1A, l1A), lengthATR) * AtrFactor;
def price1A = c1A + l1A + h1A;
def linDev1A = LinDev(price1A, lengthCCI);
def CCI1A = if linDev1A == 0 then 0 else (price1A - Average(price1A, lengthCCI)) / linDev1A / 0.015;
def MT1 = if CCI1A > 0
          then Max(MT1[1], pricedata1A - ATRcci1A)
          else Min(MT1[1], pricedata1A + ATRcci1A);
plot MT1_Dot = if IsNaN(close) then Double.NaN else -19;
MT1_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MT1_Dot.SetLineWeight(DotSize);
MT1_Dot.AssignValueColor(if c1A < MT1 then GlobalColor("TrendDown") else GlobalColor("TrendUp"));
AddChartBubble(!IsNaN(close[n1]) and IsNaN(close[n]), -19, (agg1TM / 1000 / 60) + " min", Color.YELLOW, yes);

# AGGREGATION 2

def c2A = close(period = agg2TM);
def h2A = high(period = agg2TM);
def l2A = low(period = agg2TM);
def pricedata2A = hl2(period = agg2TM);
def ATRcci2A = Average(TrueRange(h2A, c2A, l2A), lengthATR) * AtrFactor;
def price2A = c2A + l2A + h2A;
def linDev2A = LinDev(price2A, lengthCCI);
def CCI2A = if linDev2A == 0 then 0 else (price2A - Average(price2A, lengthCCI)) / linDev2A / 0.015;
def MT2 = if CCI2A > 0
          then Max(MT2[1], pricedata2A - ATRcci2A)
          else Min(MT2[1], pricedata2A + ATRcci2A);
plot MT2_Dot = if IsNaN(close) then Double.NaN else 19;
MT2_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MT2_Dot.SetLineWeight(DotSize);
MT2_Dot.AssignValueColor(if c2A < MT2 then GlobalColor("TrendDown") else GlobalColor("TrendUp"));
AddChartBubble(!IsNaN(close[n1]) and IsNaN(close[n]), 19, (agg2TM / 1000 / 60) + " min", Color.YELLOW, yes);

# AGGREGATION 3

def c3A = close(period = agg3TM);
def h3A = high(period = agg3TM);
def l3A = low(period = agg3TM);
def pricedata3A = hl2(period = agg3TM);

def ATRcci3A = Average(TrueRange(h3A, c3A, l3A), lengthATR) * AtrFactor;
def price3A = c3A + l3A + h3A;
def linDev3A = LinDev(price3A, lengthCCI);
def CCI3A = if linDev3A == 0 then 0 else (price3A - Average(price3A, lengthCCI)) / linDev3A / 0.015;
def MT3 = if CCI3A > 0
          then Max(MT3[1], pricedata3A - ATRcci3A)
          else Min(MT3[1], pricedata3A + ATRcci3A);
plot MT3_Dot = if IsNaN(close) then Double.NaN else -23;
MT3_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MT3_Dot.SetLineWeight(DotSize);
MT3_Dot.AssignValueColor(if c3A < MT3 then GlobalColor("TrendDown") else GlobalColor("TrendUp"));
AddChartBubble(!IsNaN(close[n1]) and IsNaN(close[n]), -23, (agg3TM / 1000 / 60) + " min", Color.YELLOW, yes);
# End Trend Magic MTF
#
# SuperTrend Multiple Time Frames
# Mobius with mods by tomsk to replace the script() function for secondary aggs with "standard" code
# V03.01.2016
# 11.4.2019

#declare lower;

input agg1ST = AggregationPeriod.Five_Min;
input agg2ST = AggregationPeriod.Ten_Min;
input agg3ST = AggregationPeriod.Fifteen_Min;
input agg4ST = AggregationPeriod.Thirty_Min;
input agg5ST = AggregationPeriod.Hour;
input AtrMult = .70;
input nATR = 4;
input AvgType = AverageType.HULL;

def Fh = FundamentalType.High;
def Fl = FundamentalType.Low;
def Fc = FundamentalType.Close;
def Fhl2 = FundamentalType.HL2;

def cl = close;
def x = isNaN(cl[2]) and !isNaN(cl[3]);
def ATR = MovingAverage(AvgType, TrueRange(high, close, low), nATR);
def UP = hl2 + (AtrMult * ATR);
def DN = hl2 + (-AtrMult * ATR);
def S1A = if close < S1A[1]
then Round(UP / tickSize(), 0) * tickSize()
else Round(DN / tickSize(), 0) * tickSize();
def FirstAgg = if close > S1A then 1 else 0;
plot FirstAggPlot = if isNaN(cl)
then double.nan
else -21;
FirstAggPlot.SetStyle(Curve.Points);
FirstAggPlot.SetLineWeight(3);
FirstAggPlot.AssignValueColor(if FirstAgg == 1
then color.green
else color.red);
AddChartBubble(x, 1, (GetAggregationPeriod()/1000/60) + " min", color.white, yes);

# SecondAgg
def h2 = Fundamental(Fh, period = agg2ST)[1];
def l2 = Fundamental(Fl, period = agg2ST)[1];
def c2 = Fundamental(Fc, period = agg2ST)[1];
def hl2 = Fundamental(Fhl2, period = agg2ST)[1];
def ATR2 = MovingAverage(AvgType, TrueRange(h2, c2, l2), nATR);
def UP2 = hl2 + (AtrMult * ATR2);
def DN2 = hl2 + (-AtrMult * ATR2);
def S2A = if c2 < S2A[1]
then Round(UP2 / tickSize(), 0) * tickSize()
else Round(DN2 / tickSize(), 0) * tickSize();
def SecondAgg = if c2 > S2A then 1 else 0;
plot SecondAggPlot = if isNaN(cl)
then double.nan
else 21;
SecondAggPlot.SetStyle(Curve.Points);
SecondAggPlot.SetLineWeight(3);
SecondAggPlot.AssignValueColor(if SecondAgg == 1
then color.green
else color.red);
AddChartBubble(x, 2, (agg2ST/1000/60) + " min", color.white, yes);

# ThirdAgg
def h3 = Fundamental(Fh, period = agg3ST)[1];
def l3 = Fundamental(Fl, period = agg3ST)[1];
def c3 = Fundamental(Fc, period = agg3ST)[1];
def hl3 = Fundamental(Fhl2, period = agg3ST)[1];
def ATR3 = MovingAverage(AvgType, TrueRange(h3, c3, l3), nATR);
def UP3 = hl3 + (AtrMult * ATR3);
def DN3 = hl3 + (-AtrMult * ATR3);
def S3 = if c3 < S3[1]
then Round(UP3 / tickSize(), 0) * tickSize()
else Round(DN3 / tickSize(), 0) * tickSize();
def ThirdAgg = if c3 > S3 then 1 else 0;
plot ThirdAggPlot = if isNaN(cl)
then double.nan
else 23;
ThirdAggPlot.SetStyle(Curve.Points);
ThirdAggPlot.SetLineWeight(3);
ThirdAggPlot.AssignValueColor(if ThirdAgg == 1
then color.green
else color.red);
AddChartBubble(x, 3, (agg3ST/1000/60) + " min", color.white, yes);

# FourthAgg
def h4 = Fundamental(Fh, period = agg4ST)[1];
def l4 = Fundamental(Fl, period = agg4ST)[1];
def c4 = Fundamental(Fc, period = agg4ST)[1];
def hl4 = Fundamental(Fhl2, period = agg4ST)[1];
def ATR4 = MovingAverage(AvgType, TrueRange(h4, c4, l4), nATR);
def UP4 = hl4 + (AtrMult * ATR4);
def DN4 = hl4 + (-AtrMult * ATR4);
def S4 = if c4 < S4[1]
then Round(UP4 / tickSize(), 0) * tickSize()
else Round(DN4 / tickSize(), 0) * tickSize();
def FourthAgg = if c4 > S4 then 1 else 0;
plot FourthAggPlot = if isNaN(cl)
then double.nan
else 25;
FourthAggPlot.SetStyle(Curve.Points);
FourthAggPlot.SetLineWeight(3);
FourthAggPlot.AssignValueColor(if FourthAgg == 1
then color.green
else color.red);
AddChartBubble(x, 4, (agg4ST/1000/60) + " min", color.white, yes);

# FifthAgg
def h5 = Fundamental(Fh, period = agg5ST)[1];
def l5 = Fundamental(Fl, period = agg5ST)[1];
def c5 = Fundamental(Fc, period = agg5ST)[1];
def hl5 = Fundamental(Fhl2, period = agg5ST)[1];
def ATR5 = MovingAverage(AvgType, TrueRange(h5, c5, l5), nATR);
def UP5 = hl5 + (AtrMult * ATR5);
def DN5 = hl5 + (-AtrMult * ATR5);
def S5 = if c5 < S5[1]
then Round(UP5 / tickSize(), 0) * tickSize()
else Round(DN5 / tickSize(), 0) * tickSize();
def FifthAgg = if c5 > S5 then 1 else 0;
plot FifthAggPlot = if isNaN(cl)
then double.nan
else 27;
FifthAggPlot.SetStyle(Curve.Points);
FifthAggPlot.SetLineWeight(3);
FifthAggPlot.AssignValueColor(if FifthAgg == 1
then color.green
else color.red);
AddChartBubble(x, 5, (agg5ST/1000/60)+ " min", color.white, yes);
plot Six = if isNaN(cl)
then double.nan
else 0;
Six.SetStyle(Curve.Points);
Six.SetLineWeight(3);
Six.AssignValueColor(if FirstAgg and
SecondAgg and
ThirdAgg and
FourthAgg and
FifthAgg
then color.green
else if !FirstAgg and
!SecondAgg and
!ThirdAgg and
!FourthAgg and
!FifthAgg
then color.red
else color.black);
# End Code ST MTF
 

BenTen

Administrative
Staff member
Staff
VIP
@islandcowgirl Hmmm, maybe this?

Code:
def condition_green = FirstAgg and SecondAgg and ThirdAgg and FourthAgg and FifthAgg;

def condition_red = !FirstAgg and !SecondAgg and !ThirdAgg and !FourthAgg and !FifthAgg;

Alert(condition_green, " ", Alert.Bar, Sound.Chimes);

Alert(condition_red, " ", Alert.Bar, Sound.Chimes);
 

islandcowgirl

New member
VIP
@BenTen I think that worked. I will have to further test it Monday. You're the best!
Thank you! My eyes were going crazy trying to look at multiple charts for setups.
 

Nicksmo

New member
VIP
i was wondering if there was a way to create a signal that could show a 0 or 1 value for if all agregation periods turned within 1 or two bars...i have been seeing a cood confluence to a sizable move when the 5/15/30 all turn at once...i cant seem to get it to work...i tried:

plot MTFsignal = "Main" > "Signal" and "Main2" > "Signal2" and "Main3" > "Signal3";

but saying "expected double"

i was later going to add to a watch list or possible scan to catch these moves!
Here is a clean unadulerated version of Mobius TMO with Higher Aggregation for you to play with

Code:
# TMO ((T)rue (M)omentum (O)scillator) With Higher Aggregation
# Mobius
# V01.05.2018
# 5.15.2018
#hint: TMO calculates momentum using the delta of price. Giving a much better picture of trend, tend reversals and divergence than momentum oscillators using price.

declare Lower;

input length = 14;
input calcLength = 5;
input smoothLength = 3;
input agg = AggregationPeriod.Fifteen_min;

def o = open(period = agg);;
def c = close(period = agg);
def data = fold i = 0 to length
           with s
           do s + (if c > getValue(o, i)
                   then 1
                   else if c < getValue(o, i)
                        then - 1
                        else 0);
def EMA5 = ExpAverage(data, calcLength);
plot Main = ExpAverage(EMA5, smoothLength);
plot Signal = ExpAverage(Main, smoothLength);
     Main.AssignValueColor(if Main > Signal
                           then color.green
                           else color.red);
     Signal.AssignValueColor(if Main > Signal
                             then color.green
                             else color.red);
     Signal.HideBubble();
     Signal.HideTitle();
addCloud(Main, Signal, color.green, color.red);
plot zero = if isNaN(c) then double.nan else 0;
     zero.SetDefaultColor(Color.gray);
     zero.hideBubble();
     zero.hideTitle();
plot ob = if isNaN(c) then double.nan else round(length * .7);
     ob.SetDefaultColor(Color.gray);
     ob.HideBubble();
     ob.HideTitle();
plot os = if isNaN(c) then double.nan else -round(length * .7);
     os.SetDefaultColor(Color.gray);
     os.HideBubble();
     os.HideTitle();
addCloud(ob, length, color.light_red, color.light_red, no);
addCloud(-length, os, color.light_green, color.light_green);
# End Code TMO with Higher Aggregation
 

rad14733

Well-known member
VIP
@Nicksmo You cannot have variables in quotes... Nix the quotes and it might work...

Ruby:
plot MTFsignal = Main > Signal and Main2 > Signal2 and Main3 > Signal3;
 

Nicksmo

New member
VIP
@rad14733 perfect thanks! do you know if i would be able to have this as a column on watchlist and scanner? i try to put it in the scanner and it wont seem to recognize it...
 

rad14733

Well-known member
VIP
perfect thanks! do you know if i would be able to have this as a column on watchlist and scanner? i try to put it in the scanner and it wont seem to recognize it...

You should be able to reference the Study instead of loading the entire script into the scanner... Something like:

Ruby:
def Main = reference TMO.Main;
def Signal = reference TMO.Signal;
def Main2 = reference TMO.Main2;
def Signal2 = reference TMO.Signal2;
def Main3 = reference TMO.Main3;
def Signal3 = reference TMO.Signal3;
plot MTFsignal = Main > Signal and Main2 > Signal2 and Main3 > Signal3;

If it doesn't work then what @BenTen said...
 

Similar threads

Top