@guyonabuffalo The market is closed at the moment. You will only get the alert when you have the chart displayed.
#
# Hull Moving Average Concavity and Turning Points
# or
# The Second Derivative of the Hull Moving Average
#
# Author: Seth Urion (Mahsume)
# Version: 2020-02-21 Initial Public
#
# This code is licensed (as applicable) under the GPL v3
# Version 2021-01-13 H Kaczmarczyk added Deviation Bands Ver2
# ----------------------
declare upper;
input price = HL2;
input HMA_Length = 21;
input lookback = 2;
Input BandLength = 34;
Input Deviation = 1.3185;
plot HMA = HullMovingAvg(price = price, length = HMA_Length);
plot UZone = SimpleMovingAvg(HMA, BandLength) + (Deviation * StDev(HMA, BandLength));
plot LZone = SimpleMovingAvg(HMA, Bandlength) - (Deviation * StDev(HMA, BandLength));
Plot MidZone = (UZone-LZone)/2 + LZone;
UZone.SetStyle(Curve.Medium_DASH);
UZone.SetDefaultColor(Color.CYAN);
MidZone.SetStyle(Curve.Short_DASH);
MidZone.SetDefaultColor(Color.CYAN);
LZone.SetStyle(Curve.Medium_DASH);
LZone.SetDefaultColor(Color.CYAN);
# def delta_per_bar =
# (fold n = 0 to lookback with s do s + getValue(HMA, n, lookback - 1)) / lookback;
def delta = HMA[1] - HMA[lookback + 1];
def delta_per_bar = delta / lookback;
def next_bar = HMA[1] + delta_per_bar;
def concavity = if HMA > next_bar then 1 else -1;
plot turning_point = if concavity[-1] != concavity then HMA else double.nan;
HMA.AssignValueColor(color = if concavity == -1 then
if HMA > HMA[1] then color.dark_orange else color.red else
if HMA < HMA[1] then color.dark_green else color.green);
HMA.SetLineWeight(3);
turning_point.SetLineWeight(4);
turning_point.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
turning_point.SetDefaultColor(color.white);
plot MA_Max = if HMA[-1] < HMA and HMA > HMA[1] then HMA else Double.NaN;
MA_Max.SetDefaultColor(Color.WHITE);
MA_Max.SetPaintingStrategy(PaintingStrategy.SQUARES);
MA_Max.SetLineWeight(3);
plot MA_Min = if HMA[-1] > HMA and HMA < HMA[1] then HMA else Double.Nan;
MA_Min.SetDefaultColor(Color.WHITE);
MA_Min.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MA_Min.SetLineWeight(3);
plot sell = if turning_point and concavity == 1 then high else double.nan;
sell.SetDefaultColor(Color.DARK_ORANGE);
sell.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
sell.SetLineWeight(3);
plot buy = if turning_point and concavity == -1 then low else double.nan;
buy.SetDefaultColor(Color.CYAN);
buy.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
buy.SetLineWeight(3);
def divergence = HMA - next_bar;
addLabel(yes, concat("DIVERGENCE: " , divergence), color = if concavity < 0 then if divergence[1] > divergence then Color.RED else color.PINK else if divergence[1] < divergence then color.green else color.yellow);
@mashume How about calculating the price at which the lower indicator will cross the zero line and have it as a label?@mashume Have there been any thoughts/attempts at projecting either the lower or the upper out into the future, or would that just be a fools-errand? I know the lower is already displaced by -1, but was wondering if either could be pushed out with an extension script.
Reversing the calculation of the HMA is not a trivial task. One of these days, I'll post about the calculation of reverse moving averages, but it gets quite messy, quite quickly. I looked into the idea once upon a time and decided to move on. Perhaps it would be possible to have a set of labels that showed what would happen if the price were to move up or down a certain distance or set of distances (+- 5c, +- 10c, etc...) because that would simply be adding a fake (test) value to the array of values used in the calculation and testing to see whether the indicator had moved over or under the desired point. But that's an exercise for a very bored afternoon. Maybe tomorrow. ;-)@mashume How about calculating the price at which the lower indicator will cross the zero line and have it as a label?
SMA(CLOSE, 3) := (CLOSE + CLOSE[1] + CLOSE[2]) / 3
(10 + 10 + 10) / 3 = 10
(9 + 10 + 11) / 3 = 10
(9 + 10 + x) / 3 = 10
x = -9 -10 + 30
x = -CLOSE[1] - CLOSE[2] - CLOSE[3] - CLOSE[4] + 5 * DESIRED_VALUE
HMA= WMA(2*WMA(n/2) − WMA(n)),sqrt(n))
WMA = (P1 * 5) + (P2 * 4) + (P3 * 3) + (P4 * 2) + (P5 * 1) / (5 + 4 + 3 + 2 + 1)
HMA(4) = 2 * ((2*((CLOSE[0] * 2) + (CLOSE[1] * 1) / (2 + 1)) − ((CLOSE[0] * 4) + (CLOSE[1] * 3) + (CLOSE[2] * 2) + (CLOSE[3] * 1) / (4 + 3 + 2 + 1))) * 2) + ((2*((CLOSE[1] * 2) + (CLOSE[2] * 1) / (2 + 1)) − ((CLOSE[1] * 4) + (CLOSE[2] * 3) + (CLOSE[3] * 2) + (CLOSE[4] * 1) / (4 + 3 + 2 + 1))) * 1)
CLOSE[0] -> x
CLOSE[1] -> a
CLOSE[2] -> b
CLOSE[3] -> c
CLOSE[4] -> d
HMA = 2 * ((2*((x * 2) + (a * 1) / (2 + 1)) − ((x * 4) + (a * 3) + (b * 2) + (c * 1) / (4 + 3 + 2 + 1))) * 2) + ((2*((a * 2) + (b * 1) / (2 + 1)) − ((a * 4) + (b * 3) + (c * 2) + (d * 1) / (4 + 3 + 2 + 1))) * 1) + y
from sympy.solvers import solve
from sympy import Symbol
from sympy import Eq
x = Symbol('x')
y = Symbol('y')
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
d = Symbol('d')
eq = Eq((2 * ((2*((x * 2) + (a * 1) / (2 + 1)) - ((x * 4) + (a * 3) + (b * 2) + (c * 1) / (4 + 3 + 2 + 1))) * 2) + ((2*((a * 2) + (b * 1) / (2 + 1)) - ((a * 4) + (b * 3) + (c * 2) + (d * 1) / (4 + 3 + 2 + 1))) * 1) - y), x)
solve(eq, x)
-28*a/3 - 31*b/3 - 12*c/5 - d/10 - y
-28 * CLOSE[1] / 3 - 31 * CLOSE[2] / 3 - 12 * CLOSE[3] / 5 - CLOSE[4] / 10 - 10 = x
10 + 10 + 10 + (10 + 0.5) / 4 >= 10
10 + 10 + 10 + (10 + 1.0) / 4 >= 10
10 + 10 + 10 + (10 - 0.5) / 4 >= 10
10 + 10 + 10 + (10 - 1.0) / 4 >= 10
def hl_v = if isNan(HL2[-1]) then HL2 - 10 else HL2;
input over_under = 0.5;
def hl_over_a = if isNan(HL2[-1]) then HL2 + over_under else HL2;
def hl_over_b = if isNan(HL2[-1]) then HL2 + over_under * 2 else HL2;
def hl_under_a = if isNan(HL2[-1]) then HL2 - over_under else HL2;
def hl_under_b = if isNan(HL2[-1]) then HL2 - over_under * 2 else HL2;
declare upper;
input price = HL2;
input HMA_Length = 55;
input lookback = 2;
input stddev_len = 21;
input zlength = 13;
input threshold = 1.5;
input over_under = 0.5;
def a_price = if isNan(HL2[-1]) then (LOW + (HIGH + over_under) / 2) else HL2;
def b_price = if isNan(HL2[-1]) then (LOW + (HIGH + (over_under * 2 )) / 2) else HL2;
def c_price = if isNan(HL2[-1]) then (HIGH - (LOW - over_under) / 2) else HL2;
def d_price = if isNan(HL2[-1]) then (HIGH - (LOW - (over_under * 2 )) / 2) else HL2;
# A
def a_HMA = HullMovingAvg(price = a_price, length = HMA_Length);
def a_delta = a_HMA[1] - a_HMA[lookback + 1];
def a_delta_per_bar = a_delta / lookback;
def a_next_bar = a_HMA[1] + a_delta_per_bar;
def a_divergence = (a_HMA - a_next_bar) * 5000;
def a_Zscore = ( (a_divergence - Average(a_divergence, zlength)) / StDev(a_divergence, zlength));
# B
def b_HMA = HullMovingAvg(price = b_price, length = HMA_Length);
def b_delta = b_HMA[1] - b_HMA[lookback + 1];
def b_delta_per_bar = b_delta / lookback;
def b_next_bar = b_HMA[1] + b_delta_per_bar;
def b_divergence = (b_HMA - b_next_bar) * 5000;
def b_Zscore = ( (b_divergence - Average(b_divergence, zlength)) / StDev(b_divergence, zlength));
# C
def c_HMA = HullMovingAvg(price = c_price, length = HMA_Length);
def c_delta = c_HMA[1] - c_HMA[lookback + 1];
def c_delta_per_bar = c_delta / lookback;
def c_next_bar = c_HMA[1] + c_delta_per_bar;
def c_divergence = (c_HMA - c_next_bar) * 5000;
def c_Zscore = ( (c_divergence - Average(c_divergence, zlength)) / StDev(c_divergence, zlength));
# D
def d_HMA = HullMovingAvg(price = d_price, length = HMA_Length);
def d_delta = d_HMA[1] - d_HMA[lookback + 1];
def d_delta_per_bar = d_delta / lookback;
def d_next_bar = d_HMA[1] + d_delta_per_bar;
def d_divergence = (d_HMA - d_next_bar) * 5000;
def d_Zscore = ( (d_divergence - Average(d_divergence, zlength)) / StDev(d_divergence, zlength));
AddLabel(yes, if a_Zscore > 0 then "IF High > " + (HIGH + over_under) + " Z > 0" else "High + " + (High + over_under) + " NOT < 0", if a_Zscore > 0 then color.dark_green else color.gray);
AddLabel(yes, if b_Zscore > 0 then "IF High > " + (HIGH + (2 * over_under)) + " Z > 0" else "High + " + (High + (2 * over_under)) + " NOT < 0", if a_Zscore > 0 then color.dark_green else color.gray);
AddLabel(yes, if c_Zscore > 0 then "IF Low < " + (LOW - over_under) + " Z < 0" else "Low - " + (LOW + over_under) + " NOT < 0", if a_Zscore > 0 then color.dark_red else color.gray);
AddLabel(yes, if d_Zscore > 0 then "IF Low < " + (LOW - (2 * over_under)) + " Z < 0" else "Low - " + (LOW + (2 * over_under)) + " NOT < 0", if a_Zscore > 0 then color.dark_red else color.gray);
I'm no javascript expert (most of my professional dev work is python). Can you post whatever js code you do have though and I'll be happy to try to figure it out.
-Mashume
const predef = require("./tools/predef");
const WMA = require("./tools/WMA");
class hullMovingAverage {
init() {
const period = this.props.period;
this.wmaLong = WMA(period);
this.wmaShort = WMA(period / 2);
this.wmaSqrt = WMA(Math.sqrt(period));
}
map(d) {
const value = d.value();
const wmaLong = this.wmaLong(value);
const wmaShort = this.wmaShort(value) * 2;
const wmaDiff = wmaShort - wmaLong;
return this.wmaSqrt(wmaDiff);
}
}
module.exports = {
name: "hma",
description: "Hull Moving Average",
calculator: hullMovingAverage,
params: {
period: predef.paramSpecs.period(14)
},
tags: [predef.tags.MovingAverage],
schemeStyles: predef.styles.solidLine("#8cecff")
};
const lodash = require("lodash");
const { ParamType } = require("./meta");
function mkStyle(style) {
if (typeof style === "string") {
style = { color: style };
}
return {
color: style.color || "gray",
lineWidth: style.lineWidth || 1,
opacity: style.opacity || 100,
lineStyle: style.lineStyle || 1
};
}
module.exports = {
plotters: {
line: { type: "line" },
multiline(fields) {
return {
type: "multiline",
fields
};
},
singleline(field) {
return {
type: "multiline",
fields: [field]
};
},
pivotpoints(fields) {
return {
type: "pivotpoints",
fields
};
},
histogram: { type: "histogram" },
cumulative: { type: "cumulative" },
zigzag(fields) {
return {
type: "zigzag",
fields
};
},
macd: { type: "macd" },
scatter: { type: "scatter" },
dots(field) {
return {
type: "dots",
field: field || "_"
};
},
columns(field) {
return {
type: "columns",
field
};
},
custom(func) {
return {
type: "custom",
function: func
};
},
range(fieldFrom, fieldTo) {
return {
type: "range",
fields: [fieldFrom, fieldTo]
};
}
},
scalers: {
singlePath: { type: "singlePath" },
multiPath(fields) {
return {
type: "multiPath",
fields
};
}
},
paramSpecs: {
period(defValue) {
return {
type: ParamType.NUMBER,
def: defValue,
restrictions: {
step: 1,
min: 1
},
validate(value) {
if (value < 1) {
return "Period should be a positive number";
}
return undefined;
}
};
},
number(defValue, step, min) {
return {
type: ParamType.NUMBER,
def: defValue,
restrictions: {
step: step || 1,
min: min || 0
}
};
},
percent(defValue, step, min, max) {
return {
type: ParamType.NUMBER,
def: defValue,
restrictions: {
step: step || 1,
min,
max
}
};
},
bool(defValue) {
return {
type: ParamType.BOOLEAN,
def: defValue
};
},
text(defValue) {
return {
type: ParamType.TEXT,
def: defValue
};
},
enum(enumSet, defValue) {
return {
type: ParamType.ENUM,
enumSet,
def: defValue,
toSelectOptions() {
return lodash.toPairs(enumSet)
.map(p => ({
label: p[1],
value: p[0]
}));
}
};
},
color(defValue) {
return {
type: ParamType.COLOR,
def: defValue
};
}
},
filters: {
onlyNumberValue(d) {
return d && (typeof d.value === "number" && !isNaN(d.value) || typeof d === "object");
},
isNumber(d) {
return typeof d === "number" && !isNaN(d);
}
},
tags: {
MovingAverage: "Moving Averages",
Channels: "Channels",
Volatility: "Volatility",
Oscillators: "Oscillators",
Volumes: "Volume-based"
},
styles: {
solidLine(plotName, dark, light) {
if (arguments.length === 1) {
dark = plotName;
plotName = "_";
}
if (!light) {
light = dark;
}
const result = {
dark: {},
light: {}
};
result.dark[plotName] = mkStyle(dark);
result.light[plotName] = mkStyle(light);
return result;
},
plot(partialStyle) {
return mkStyle(partialStyle);
},
dashLine(plotName, dark, light) {
if (arguments.length === 1) {
dark = plotName;
plotName = "_";
}
if (!light) {
light = dark;
}
const result = {
dark: {},
light: {}
};
result.dark[plotName] = mkStyle(dark);
result.dark[plotName].lineStyle = 3;
result.light[plotName] = mkStyle(light);
result.light[plotName].lineStyle = 3;
return result;
},
}
};
function triangular(value) {
return (value / 2) * (value + 1);
}
function WeightedMovingAverage(period) {
function wma(value) {
return wma.push(value);
}
wma.reset = () => {
wma.state = {
items: []
};
};
wma.push = (value) => {
wma.state.items.push(value);
if (wma.state.items.length > period) {
wma.state.items.shift();
}
return wma.avg();
};
wma.avg = () => {
const items = wma.state.items;
const denominator = triangular(items.length);
function wmaAccumulator(sum, value, index) {
return sum + (value * (index + 1) / denominator);
}
return items.reduce(wmaAccumulator, 0);
};
wma.reset();
return wma;
}
module.exports = WeightedMovingAverage;
Sure....if you add this indicator to your "on demand" function, you will be able to back test.Great indicator, is there anyway to backtest and show profit and loss? or run as a scan?
replying to my own question/request like the sad puppy i am. I think this covers it bu would be grateful if someone could check my code please.Ok here's a thought. Labels to show the polarity of this indicator from a higher timeframe (e.g. 2m position on a 1m chart). I use this for confirmation when entering i.e. if the positive turning point (Dark Green line) has fired on the higher timeframe i can enter with higher risk, if the Buy signal (Green line) has fired i can enter with low risk.
I'm going to attempt to code this now but hoping someone who actually knows what they are doing can help while i bumble about in the meantime ;-)
@rad14733 apologies, I hadn't considered that folks might not want to import my potentially p!ss poor code into there TOS! Here's the code:@BBDPDC Can you post the code, using the </> icon, for review without the need to import into TOS please... Please make it a habit to always post the code, not just a shared link...
#Hull HigherAgg Label
declare upper;
input price = HL2;
input HMA_Length = 18;
input lookback = 1;
input agg = { "1 min", default "2 min", "5 min", "10 min", "15 min", "30 min", "60 min", "4 hours"};
def nan = double.nan;
def HMA = HullMovingAvg(HL2(period=agg), HMA_Length);
def delta = HMA[1] - HMA[lookback + 1];
def delta_per_bar = delta / lookback;
def next_bar = HMA[1] + delta_per_bar;
def concavity = if HMA > next_bar then 1 else -1;
def turning_point = if concavity[1] != concavity then HMA else nan;
AddLabel(yes, "HULL", color = if concavity[1] == -1 then
if HMA > HMA[1] then color.dark_orange else color.red else
if HMA < HMA[1] then color.dark_green else color.green);
This indicator is awesome! Is there a way to scan for MA_Min alert and MA_Max alert? I changed it to VWAP 30, 2 and love it on the 15mn and the 30mn. Buy on the Min and sell on the Max. Also how could I make this a buy script? All based on the upper script I have a 6yo in online Kindergarten so it's hard to watch charts now.Thank you all for your comments and encouragement.
I have a laundry list of things in this post:
- Variations to scripts
- Scanner
- Testing
Script Variations
@chillc15, I'm intrigued by the Arnaud Legoux MA, and so here is a variant of the upper study that will allow you to choose between Hull, Simple, Exponential, Williams, and ALMA. I haven't gone through the various permutations, but bear in mind that the 'overshoot' and smoothing of the Hull is part of what makes the turning point signal so attractive.
@Miket Used your posted code for the ALMA. Hope you're good with this use. Thanks!
Code:# # Multiple Moving Average Concavity and Turning Points # or # The Second Derivative of the A Moving Average # # via useThinkScript # request from chillc15 # Added Arnaud Legoux MA and other Moving Averages # # Author: Seth Urion (Mahsume) # Version: 2020-02-22 V2 # # This code is licensed (as applicable) under the GPL v3 # # ---------------------- declare upper; input price = HL2; input MA_Length = 21; input lookback = 2; input MovingAverage = {default "HMA", "EMA", "SMA", "WMA", "ALMA"}; script ALMA { # Attributed to Miket # https://tos.mx/9mznij # https://usethinkscript.com/threads/alma-arnaud-legoux-ma-indicator-for-thinkorswim.174/ input Data = close; input Window = 9; input Sigma = 6; input Offset = 0.85; def m = (Offset * (Window - 1)); def s = Window/Sigma; def SumVectorData = fold y = 0 to Window with WS do WS + Exp(-(sqr(y-m))/(2*sqr(s))) * getvalue(Data, (Window-1)-y); def SumVector = fold z = 0 to Window with CW do CW + Exp(-(sqr(z-m))/(2*sqr(s))); plot ALMA = SumVectorData / SumVector; } plot MA; switch (MovingAverage) { case EMA: MA = MovAvgExponential(price, length = MA_Length); case SMA: MA = simpleMovingAvg(price, length = MA_Length); case WMA: MA = wma(price, length = MA_Length); case ALMA: MA = ALMA(Data = price, window = MA_Length); default: MA = HullMovingAvg(price = price, length = MA_Length); } def delta = MA[1] - MA[lookback + 1]; def delta_per_bar = delta / lookback; def next_bar = MA[1] + delta_per_bar; def concavity = if MA > next_bar then 1 else -1; plot turning_point = if concavity[-1] != concavity then MA else double.nan; MA.AssignValueColor(color = if concavity == -1 then if MA > MA[1] then color.dark_orange else color.red else if MA < MA[1] then color.dark_green else color.green); MA.SetLineWeight(3); turning_point.SetLineWeight(4); turning_point.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS); turning_point.SetDefaultColor(color.white); plot MA_Max = if MA[-1] < MA and MA > MA[1] then MA else Double.NaN; MA_Max.SetDefaultColor(Color.WHITE); MA_Max.SetPaintingStrategy(PaintingStrategy.SQUARES); MA_Max.SetLineWeight(3); plot MA_Min = if MA[-1] > MA and MA < MA[1] then MA else Double.Nan; MA_Min.SetDefaultColor(Color.WHITE); MA_Min.SetPaintingStrategy(PaintingStrategy.TRIANGLES); MA_Min.SetLineWeight(3); plot sell = if turning_point and concavity == 1 then high else double.nan; sell.SetDefaultColor(Color.DARK_ORANGE); sell.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN); sell.SetLineWeight(3); plot buy = if turning_point and concavity == -1 then low else double.nan; buy.SetDefaultColor(Color.CYAN); buy.SetPaintingStrategy(PaintingStrategy.ARROW_UP); buy.SetLineWeight(3); def divergence = MA - next_bar; addLabel(yes, concat("DIVERGENCE: " , divergence), color = if concavity < 0 then if divergence[1] > divergence then Color.RED else color.PINK else if divergence[1] < divergence then color.green else color.yellow);
SCANS
@mailbagman2000 , Scans, yes...
Scan 1 -- Buy signals.
This scan relies on the upper study being called "Concavity" and is entered on the scan page as a custom.
Code:Concavity("hma length" = 55, price = CLOSE)."buy" is true within 2 bars
Scan 2 -- Stocks approaching possible Buy signals
I thought that, since the lower indicator crossovers can generate signals, that an 'early warning' scan might be of interest. We can scan for any HMA that has a negative convergence, and look for a decrease in the distance below zero. It may be a long way off, it may never get there, but we are alerted before the trade entry.
Code:script ConcavityDivergence { # # Hull Moving Average Concavity Divergence # or # The Second Derivative of the Hull Moving Average # # Author: Seth Urion (Mahsume) # Version: 2020-02-21 Initial Public # # This code is licensed (as applicable) under the GPL v3 # # ---------------------- declare lower; input price = HL2; input HMA_length = 34; input lookback = 2; def HMA = HullMovingAvg(length = HMA_length, price = price); def delta = HMA[1] - HMA[lookback + 1]; def delta_per_bar = delta / lookback; def next_bar = HMA[1] + delta_per_bar; def concavity = if HMA > next_bar then 1 else -1; plot zero = 0; zero.setdefaultcolor(color.gray); zero.setpaintingstrategy(PaintingStrategy.DASHES); plot divergence = displacer(-1, HMA - next_bar); divergence.setDefaultColor(Color.LIME); divergence.SetLineweight(2); plot cx_up = if divergence crosses above zero then 0 else double.nan; cx_up.SetPaintingStrategy(PaintingStrategy.POINTS); cx_up.SetDefaultColor(Color.LIGHT_GREEN); cx_up.SetLineWeight(4); plot cx_down = if divergence crosses below zero then 0 else double.nan; cx_down.SetPaintingStrategy(PaintingStrategy.POINTS); cx_down.SetDefaultColor(Color.RED); cx_down.SetLineWeight(4); } def signal = ConcavityDivergence("hma length" = 55)."concavity"; def HMA = ConcavityDivergence("hma length" = 55)."HMA"; def next = ConcavityDivergence("hma length" = 55)."next_bar"; plot buy = signal < 0 and (HMA - next) > (HMA[1] - next[1]);
TESTING
I used the built-in strategy feature of thinkorswim, with block sizes of 100. All tests were run on 1 year Daily charts, with an HMA length of 55 and set price to CLOSE
First SPX
Buy and Hold: $55,600
Strategy: $77,372
Delta + $21772
Next ADI
Buy and Hold: $1718
Strategy: $5202
Delta: + $3483
Last BA
Buy and Hold: ($9322)
Strategy: $14393
Delta: + $23715
SHORT TIME FRAMES
I did not take time today to test shorter timeframes, though I imagine the results would be good. If there is interest, I'll try to post up some another time.
If you've read this far, thank you.
Happy trading and good luck.
Join useThinkScript to post your question to a community of 21,000+ developers and traders.
Thread starter | Similar threads | Forum | Replies | Date |
---|---|---|---|---|
S | Exponential Hull Moving Average (EHMA) for ThinkorSwim | Indicators | 8 | |
Safe Hull Moving Average Indicator for ThinkorSwim | Indicators | 3 | ||
Hull Format, Label, Watchlist, Scan for ThinkorSwim | Indicators | 115 | ||
L | A Volume Pressure Moving Average For ThinkOrSwim | Indicators | 15 | |
T | Mega Moving Average For ThinkOrSwim | Indicators | 26 |
Start a new thread and receive assistance from our community.
useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.
We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.
If you are new, or just looking for guidance, here are some helpful links to get you started.