Local Hurst Exponent for ThinkorSwim

sniktau

New member
Hello forum members,

I am happy to release the first pass at a simple, local approximation of the Hurst exponent. This is a work in progress and this post is already taking up too much of my lunch hour.

What is the Hurst Exponent?

It's a measure of a time-series' feedback on itself, or its memory. If the exponent is found to be 1/2, the time series is moving "truly" randomly, and towards 1 or 0 it is either displaying positive feedback or negative feedback, respectively. It was developed by the hydrologist Harol Edwin Hurst in the 1950's to figure out how large to make a dam to deal with all of the possible flooding outcomes. It is directly related to the fractal dimension D. Please read more from Wikipedia or (Mis)Behavior of Markets by Mandelbrot.

The equation from Wikipedia is as follows:

d32a26032869f8c902eb7a3062309dd88de63b5b


Hurst used the following equation for the Nile. He found it to be ~0.73 for that river.

2IEEZWV.png

  • R( n) is the range of the first n cumulative deviations from the mean, and S( n) their standard deviation, in the case of Hurst's research, the regular standard distribution is used. Mandelbrot cautions again and again in his book about being wary of such a measure because he claims markets are not governed by Gaussians, but by a mix of Cauchy and Gaussian distributions.
  • E s the expected value
  • n is the time span of the observation (number of data points in a time series)
  • C is a constant.

Mandelbrot suggests the following for R/S from p. 288 of the referenced book:


(LaTeX because it was a pain to write: \frac{R( n)}{S( n)} = \frac {\max\limits_{1 \leq k \leq n} \sum\limits_{j=1}^k (r_j - \bar{r_n}) - \min\limits_{1 \leq k \leq n} \sum\limits_{j=1}^k (r_j - \bar{r_n})} {\bigg( \sum\limits_{j} (r_j - \bar{r_n})^2\bigg)^\frac{1}{2}} )

h1dwW1c.png


  • r is the return
  • r bar is the average return
  • n is the max time range
  • k is the index for the sums

... What?

Okay what does it mean that it's related to the fractal dimension? It basically means that for a time series, the value of H corresponds to how rough the time series is. Let me break it down:
  • When H is near 1 is implies persistency:
    • positive feedback is at work
    • all investors are bullish or bearish
    • what to watch for: volume dropping off since everyone has made their bets, the market losing steam and going sideways
  • When H is exactly 1/2 is implies random:
    • The stochastic time-series events are independent of each other. No memory or feedback
    • What to watch for: conventional finance theories rejoicing temporarily
  • When H is near 0 it implies reversion:
    • negative feedback
    • tug-of-war, choppy, rough
    • what to watch for: chartists mentioning the market coiling up, possibly a change in volatility
This measurement is taken over multiple timescales, ideally disparate-scaled ones extending deep, deep into the past.

That seems like that math takes ages to do in thinkscript, is there a faster way?

As mentioned in another post, here is a local approximation of the Hurst exponent which can be used:

AMwuWqO.png

  • Where h is the highest high in the time range,
  • l is the lowest low in the time range,
  • t is the time period over which measurements are taken
  • average_*true*_range is the average true price range
  • C is a correction factor... ExtremeHurst has some other part that considers log-periodic oscillations... not going into that
Local to what? That time range. The Hurst exponent for one time range is hardly insightful. It is more useful to see what it is at multiple timescales. Which, finally brings us to:

Plotting Hurst in ThinkorSwim

Here is the thinkscript study:

Rich (BB code):
input length = 4;
input averageType = AverageType.EXPONENTIAL;

def ll = Lowest(low[1], length);
def hh = Highest(high[1], length);
def atr = MovingAverage(averageType, TrueRange(high, close, low), length);

plot H;

def tmp_H = (Log(hh - ll) - Log(atr)) / (Log(length));

if H > 1 then {
  H = 1;
} else if H < 0 {
  H = 0;
} else {
  H = tmp_H;
}

I suggest you run it in thermo mode. I've been using a range of 3-32. I tried making defaults in the above script but it breaks ToS...

TL;DR: Shared link. This is on top of @YungTraderFromMontana's wonderful charting setup, FYI: https://tos.mx/mFd0SQZ

What about that correction factor? Where's the _______ ?

This script sucks. I have the following improvements to make:
  • Make it work over multiple time frames. Right now it just descends some length ticks into the past at the current timescale. This limits the utility
  • Make defaults. Especially the mid color and range for the thermo plot
  • Make it display semilog data; we want to peek deep deep into the time series and see what's frothing in the short term.
  • Make alerts for when persistency or antipersistency is appearing across multiple timescales.
  • Model log-periodic oscillations, esp. near binary events
  • Account for the multifractal nature of trading time
 
Last edited:

sniktau

New member
Oooh! If you haven't already, look at my first post for more on thermo mode!

The entire documentation on the thermo commands is as follows as an afterthought in an Appendix, and if you try it, it might break TOS:

Rich (BB code):
#thermo plot : Data
#thermo input : length
#thermo minValue : 10
#thermo maxValue : 50
#thermo minColor : 0, 0, 255
#thermo maxColor : 255, 255, 255

That's it.

Those aren't comments, either, they're meaningful settings and for me it broke things when I tried it out. In a way, the form reminds me of C pragmas, but I doubt that's what these are called since I'm assuming that thinkscript is interpreted. Anyway, point is: this is a very weird and underdocumented part of the thinkorswim platform. Not many settings, which makes my goal to see semi-log plots of H frustrating.

I want to know more and I am at my limits. I'll reach out to TD Ameritrade to see if I can enrich our hot, entropic, thermo-charting.
 

sniktau

New member
Good question, I think I somehow assumed along the way that high and low had to be indexed into and just never went back, I think I should change it to be at the current tick.

For the heck of it I tried using LowestAll(low) and HighestAll(high). I'm quite surprised at the difference!

Old way (well, without the unhelpful -1 indexing).

L2JCouD.png


LowestAll/HighestAll usage:

bE3XmId.png


The second case is interesting, and I suspect it might be more on the right track actually and my old plot approach is suspect.

Re-scaled magenta to be 0.5:

AMrQEq8.png


Like I said, this script needs more work...
 

sniktau

New member
This is a little awkward, @KKaiser. I don't mean to be rude in any way by posting about this subject. I realized in my response to your post, I had so much more to say and explore, that I realized I should just make a new thread with my attempt at a specific approximation. I'm not quite sure to what you're taking offense? Posting a response to your thread or posting this new thread?

As an aside: I joined this forum initially to work out how to present the Hurst exponent as well as multifractal time in a technical indicator or series of indicators, and so I had collected some stuff on the matter, but didn't know how to put it together or who to share it with, until I came here...

If its a matter of "hey I brought it up first": @BenTen can look at the edit history of my very first post here from last Thursday and see that I actually removed a reference to the Hurst exponent (I thought that it was irrelevant to that specific question and edited it after the fact, but I guess I should have been talking about Hurst in every single post after all.).
 

KKaiser

Member
VIP
Hi @sniktau, no offense, just thought we could have continue this conversation on the post I posted. I am very thankful that you that you came up with a cool formula. Sorry if I made you feel uncomfortable
 

wtf_dude

Active member
@sniktau You're going to be hard pressed to find somebody at TD or the TOS office who will really know thermo mode. Ehlers was the head of the trading division when i was there and they had just released it (he was the inventor), long story short...nobody likes or cares bout thermo. The active traders already had systems they liked and didn't want to bother learning to read a new system and newbie traders thought it looked cool but didn't know wtf to do with it. In the several years I worked with TD, I had a total of 2 callers ask about thermo mode... Anyways, they left it in because Ehlers was still there and it basically just doesn't get much use (that's why it's just an appendix footnote most likely) So unless things have MASSIVELY changed in the last 4-5 years, don't expect anybody to know anything beyond what you can find on the net.

Thermo was slapped on with the introduction of the "Swami" indicators. You can read more about how all this crap was developed here.
 
Last edited by a moderator:

GERMANB1990

New member
I found a code for hurts channel

Code:
# Hurst_Channels
#
# www.trendxplorer.info
# [email protected]
#
# Build: July 25, 2012
# Rev 1: July 27, 2012: ExtrapolatedMA based on Kirills code
# Rev 2: July 29, 2012: FlowPrice value for better extremes
# Rev 3: Sept  9, 2012: Coloring for ExtrapolatedCMA added
#

#
# --- script begin ----
#

declare upper;

input price = hl2;
input length = 10;
input InnerValue = 1.6;
input OuterValue = 2.6;
input ExtremeValue = 4.2;
input showFlowPrice = NO;
input showPriceBar = YES;
input smooth = 1;

def displacement = (-length / 2) + 1;
def dPrice = price[displacement];

rec CMA = if !IsNaN(dPrice) then Average(dPrice, AbsValue(length)) else CMA[1] + (CMA[1] - CMA[2]);

plot CenteredMA = if !IsNaN(dPrice) then CMA else Double.NaN;
CenteredMA.SetDefaultColor(GetColor(1));
CenteredMA.SetLineWeight(2);

plot ExtrapolatedMA = if !IsNaN(price) and IsNaN(dprice[-1]) then CMA else
Double.NaN;
ExtrapolatedMA.SetDefaultColor(GetColor(0));
ExtrapolatedMA.SetLineWeight(2);
ExtrapolatedMA.SetStyle(Curve.SHORT_DASH);
ExtrapolatedMA.DefineColor("Up", Color.Magenta);
ExtrapolatedMA.DefineColor("Down", Color.Yellow);
ExtrapolatedMA.AssignValueColor(if ExtrapolatedMA >= ExtrapolatedMA[1] then ExtrapolatedMA.color("Up") else ExtrapolatedMA.color("Down"));

def ExtremeBand = CMA * ExtremeValue / 100;;
def OuterBand   = CMA * OuterValue / 100;
def InnerBand   = CMA * InnerValue / 100;

plot UpperExtremeBand = if !IsNaN(price) then CMA + ExtremeBand else Double.Nan;
plot LowerExtremeBand = if !IsNaN(price) then CMA - ExtremeBand else Double.Nan;
plot UpperOuterBand   = if !IsNaN(price) then CMA + OuterBand else Double.Nan;
plot LowerOuterBand   = if !IsNaN(price) then CMA - OuterBand else Double.Nan;
plot UpperInnerBand   = if !IsNaN(price) then CMA + InnerBand else Double.Nan;
plot LowerInnerBand   = if !IsNaN(price) then CMA - InnerBand else Double.Nan;

UpperExtremeBand.SetDefaultColor(GetColor(4));
UpperExtremeBand.SetLineWeight(2);
LowerExtremeBand.SetDefaultColor(GetColor(4));
LowerExtremeBand.SetLineWeight(2);
UpperExtremeBand.hide();
LowerExtremeBand.hide();

UpperOuterBand.SetDefaultColor(GetColor(5));
UpperOuterBand.SetLineWeight(2);
LowerOuterBand.SetDefaultColor(GetColor(6));
LowerOuterBand.SetLineWeight(2);

UpperInnerBand.SetDefaultColor(GetColor(5));
UpperInnerBand.SetLineWeight(1);
UpperInnerBand.SetStyle(Curve.SHORT_DASH);
LowerInnerBand.SetDefaultColor(GetColor(6));
LowerInnerBand.SetLineWeight(1);
LowerInnerBand.SetStyle(Curve.SHORT_DASH);

# Turn AddClouds off by putting a #-sign at the first position of the lines
AddCloud(UpperOuterBand, UpperInnerBand, color.red);
AddCloud(LowerInnerBand, LowerOuterBand, color.green);

#Rev 2:
#def FlowValue = if close > close[1] then high else if close < close[1] then low else (high + low)/2;
def FlowValue =
    if high >= high[1] and low <= low[1]
    then
        if close >= close[1] #or high >= high[2]
        then high
        else low
    else
        if high > high[1]
        then high
        else
            if low < low[1]
            then low
            else
                if close > close[1]
                then high
                else
                    if close < close[1]
                    then low
                    else (high + low) / 2;

plot FlowPrice = if showFlowPrice then Average(FlowValue, smooth) else double.nan;
FlowPrice.SetDefaultColor(GetColor(9));
FlowPrice.SetLineWeight(2);

hidePricePlot(!showPriceBar);

#
# --- script end ----
#
 

YungTraderFromMontana

Well-known member
@sniktau if you ever come back to the site I'd like to chat. I've used your code as the core of an algorithm I've mad and was able to work with the issue of it calculating for only one length. I have some more ideas but I don't have the math mind to implement them, so I came back to this post hoping I could talk.
 

MatthewA

Active member
VIP
@sniktau if you ever come back to the site I'd like to chat. I've used your code as the core of an algorithm I've mad and was able to work with the issue of it calculating for only one length. I have some more ideas but I don't have the math mind to implement them, so I came back to this post hoping I could talk.
@sniktau you write so elegantly it was very nice to meet you. I won't spam your post with artwork but you open excellent thoughts of what is within an order or what is separated into isolated chaotic events...
My human eyes are limited in understanding order or chaos, but I may try for an understanding with enthalpy, entropy, dynamics etc...

Thank you for sharing.
 

sniktau

New member
Hahah! I stopped trading for a long bit to focus on work. Sorry for going dark, but I'm not dead (yet).

I've been interested in just implementing some of the ideas discussed in Mandelbrot's book. Hurst Exponent tells you the kind of memory that might be at work, but like all TA, I think choice of scale is critical and I'm not sure how to tune it. If tuned right, Hurst exponent could tell you the type of feedback that's going on (positive or negative). It's been a while since I've read it.... and I've also bought a few other books that might help me more dangerous to my own portfolio.

I have been trying to make sense of the Hurst exponent, but I think it needs to be paired with a notion of "trading time". I've been using thinkorswim's candle mode that stretches the candles when volume is big and compresses them when volume is small (equivolume), where volume is an (inverted) proxy for time compression. I wonder if this is backwards for the purposes of Hurst, but I would like to feed that "trading time" to the Hurst calculation.

I'm interested how Yung Trader Montana has been incpororating the result since I've last been active, and if there's any better ways to get a hint when there's a hustle on (fear or greed) in the market apart from Volume, and if I can make my own candle style where large volume/volatility/etc. squeezes time and boring periods are stretched, or at least favor exponents calculated at different scales as appropriate.

TLDR: Anyway, thermo+equivolume is close to what I wanted and I wanted to trade with it on my own for a while, and also work. Sorry for being quiet!

Here's my messy setup right now:
http://tos.mx/lW1aewK
 

MatthewA

Active member
VIP
I agree that Volume can be a natural accompaniment to Hurst.

In thermodynamics you take an energy balance or entropy balance 0 = 0 and so I would propose taking a disorder balance across competing events rather than favoring Hurst=1.

We should have some phone conference later... I offered @YungTraderFromMontana an NDA after he requested some very minor coding requests but he skipped town lol... I think he will turn up later as well.
https://usethinkscript.com/threads/yungtraders-relative-volume.5243/#post-50262
 

sniktau

New member
I agree that Volume can be a natural accompaniment to Hurst.

In thermodynamics you take an energy balance or entropy balance 0 = 0 and so I would propose taking a disorder balance across competing events rather than favoring Hurst=1.

We should have some phone conference later... I offered @YungTraderFromMontana an NDA after he requested some very minor coding requests but he skipped town lol... I think he will turn up later as well.
https://usethinkscript.com/threads/yungtraders-relative-volume.5243/#post-50262
I'm not sure I could give you much to work with, as I'm still a budding thinkscripter, and often frustrated by the limitations of my ignorance and the quirks of the tooling. I have some forum reading to catch up on still, I hope you've had a good month :)
 

MatthewA

Active member
VIP
I'm not sure I could give you much to work with
You have no obligation to spend hours as my librarian. It's nice to find others to discuss these sort of goals

I was happy to make the last breakout detectors for @YungTraderFromMontana. Penny stock breakouts are mostly useless now but he will probably be able use those when the FED settles it's 10 year Treasury Debts (TNX) and the next Bull market begins.
He is either busy or intent on keeping those to himself 🤫 but wherever he is I hope he is well.


Currently I wish to focus directly on Order Flow not when a security passes AllTimeHighs because I am not as knowledgeable as Yung on breakout behaviors...

I imagine almost anything will increase in value if the FED jumps in to manage their debts.
 

Similar threads

Top