Market Profile (TPOProfile) Monkey Bars for ThinkorSwim

markos

Well-known member
VIP
Here's a TPO Refined with Monkey Bars script for ThinkorSwim.

Code:
# TPO Refined with Monkey Bar Study
# Mobius
# V01.04.07.2018

input pricePerRowHeightMode = {AUTOMATIC, default TICKSIZE, CUSTOM};
input customRowHeight = 1.0;
input aggregationPeriod = {"1 min", "2 min", "3 min", "4 min", "5 min", "10 min", "15 min", "20 min", default "30 min", "1 hour", "2 hours", "4 hours", "Day", "2 Days", "3 Days", "4 Days", "Week", "Month"};
input timePerProfile = {CHART, MINUTE, HOUR, default DAY, WEEK, MONTH, "OPT EXP", BAR, YEAR};
input multiplier = 1;
input onExpansion = no;
input profiles = 5;
input showMonkeyBar = no;
input showThePlayground = no;
input thePlaygroundPercent = 70;
input opacity = 25;
input emphasizeFirstDigit = no;
input markOpenPrice = no;
input markClosePrice = no;
input volumeShowStyle = MonkeyVolumeShowStyle.NONE;
input showVolumeVA = yes;
input showVolumePoc = yes;
input theVolumePercent = 70;
input showInitialBalance = no;
input initialBalanceRange = 1;

def period;
def yyyymmdd = GetYYYYMMDD();
def seconds = SecondsFromTime(0);
def month = GetYear() * 12 + GetMonth();
def day_number = DaysFromDate(First(yyyymmdd)) + GetDayOfWeek(First(yyyymmdd));
def dom = GetDayOfMonth(yyyymmdd);
def dow = GetDayOfWeek(yyyymmdd - dom + 1);
def expthismonth = (if dow > 5 then 27 else 20) - dow;
def exp_opt = month + (dom > expthismonth);
def periodMin = Floor(seconds / 60 + day_number * 24 * 60);
def periodHour = Floor(seconds / 3600 + day_number * 24);
def periodDay = CountTradingDays(Min(First(yyyymmdd), yyyymmdd), yyyymmdd) - 1;
def periodWeek = Floor(day_number / 7);
def periodMonth = month - First(month);

switch (timePerProfile) {
case CHART:
    period = 0;
case MINUTE:
    period = periodMin;
case HOUR:
    period = periodHour;
case DAY:
    period = periodDay;
case WEEK:
    period = periodWeek;
case MONTH:
    period = periodMonth;
case "OPT EXP":
    period = exp_opt - First(exp_opt);
case BAR:
    period = BarNumber() - 1;
case YEAR:
    period = GetYear() - First(GetYear());
}

input RthBegin  = 0930;
input RthEnd    = 1600;
input Minutes = 60;
#input showBubbles = no;
def OpenRange = SecondsFromTime(0930) >= 0 and
                SecondsFromTime(1000) >= 0;
def bar = BarNumber();
def RTHBar1 = if SecondsFromTime(RthBegin) == 0 and
                 SecondsTillTime(RthBegin) == 0
              then bar
              else RTHBar1[1];
def RTHBarEnd = if SecondsFromTime(RthEnd) == 0 and
                   SecondsTillTime(RthEnd) == 0
                then 1
                else Double.NaN;
def RTH = SecondsFromTime(RthBegin) > 0 and
          SecondsTillTime(RthEnd) > 0;
def start_t = if RTH and !RTH[1]
              then GetTime()
              else start_t[1];
def t = if start_t == GetTime()
        then 1
        else GetTime() % (Minutes * 60 * 1000) == 0;
def cond = t;

def height;
switch (pricePerRowHeightMode) {
case AUTOMATIC:
    height = PricePerRow.AUTOMATIC;
case TICKSIZE:
    height = PricePerRow.TICKSIZE;
case CUSTOM:
    height = customRowHeight;
}

def timeInterval;
def aggMultiplier;
switch (aggregationPeriod) {
case "1 min":
    timeInterval = periodMin;
    aggMultiplier = 1;
case "2 min":
    timeInterval = periodMin;
    aggMultiplier = 2;
case "3 min":
    timeInterval = periodMin;
    aggMultiplier = 3;
case "4 min":
    timeInterval = periodMin;
    aggMultiplier = 4;
case "5 min":
    timeInterval = periodMin;
    aggMultiplier = 5;
case "10 min":
    timeInterval = periodMin;
    aggMultiplier = 10;
case "15 min":
    timeInterval = periodMin;
    aggMultiplier = 15;
case "20 min":
    timeInterval = periodMin;
    aggMultiplier = 20;
case "30 min":
    timeInterval = periodMin;
    aggMultiplier = 30;
case "1 hour":
    timeInterval = periodHour;
    aggMultiplier = 1;
case "2 hours":
    timeInterval = periodHour;
    aggMultiplier = 2;
case "4 hours":
    timeInterval = periodHour;
    aggMultiplier = 4;
case "Day":
    timeInterval = periodDay;
    aggMultiplier = 1;
case "2 Days":
    timeInterval = periodDay;
    aggMultiplier = 2;
case "3 Days":
    timeInterval = periodDay;
    aggMultiplier = 3;
case "4 Days":
    timeInterval = periodDay;
    aggMultiplier = 4;
case "Week":
    timeInterval = periodWeek;
    aggMultiplier = 1;
case "Month":
    timeInterval = periodMonth;
    aggMultiplier = 1;
}
def agg_count = CompoundValue(1, if timeInterval != timeInterval[1]
                                 then (GetValue(agg_count, 1) + timeInterval -
                                                  timeInterval[1]) % aggMultiplier
                                 else GetValue(agg_count, 1), 0);
def agg_cond = CompoundValue(1,  agg_count < agg_count[1] + timeInterval -
                                                            timeInterval[1], yes);
def digit = CompoundValue(1, if cond
                             then 1
                             else agg_cond + GetValue(digit, 1), 1);
profile monkey = MonkeyBars(digit,
                "startNewProfile" = cond,
                "onExpansion" = onExpansion,
                "numberOfProfiles" = profiles,
                "pricePerRow" = height,
                "the playground percent" = thePlaygroundPercent,
                "emphasize first digit" = emphasizeFirstDigit,
                "volumeProfileShowStyle" = volumeShowStyle,
                "volumePercentVA" = theVolumePercent,
                "show initial balance" = showInitialBalance,
                "initial balance range" = initialBalanceRange);
def con = CompoundValue(1, onExpansion, no);
def mbar = CompoundValue(1, if IsNaN(monkey.GetPointOfControl()) and con then GetValue(mbar, 1) else monkey.GetPointOfControl(), monkey.GetPointOfControl());
def hPG = CompoundValue(1, if IsNaN(monkey.GetHighestValueArea()) and con then GetValue(hPG, 1) else monkey.GetHighestValueArea(), monkey.GetHighestValueArea());
def lPG = CompoundValue(1, if IsNaN(monkey.GetLowestValueArea()) and con then GetValue(lPG, 1) else monkey.GetLowestValueArea(), monkey.GetLowestValueArea());
def hProfile = CompoundValue(1, if IsNaN(monkey.GetHighest()) and con then GetValue(hProfile, 1) else monkey.GetHighest(), monkey.GetHighest());
def lProfile = CompoundValue(1, if IsNaN(monkey.GetLowest()) and con then GetValue(lProfile, 1) else monkey.GetLowest(), monkey.GetLowest());
def plotsDomain = IsNaN(close) == onExpansion;
profile tpo = TimeProfile("startNewProfile" = t,
                          "onExpansion" = 0,
                          "numberOfProfiles" = profiles,
                          "pricePerRow" =  tickSize(),
                          "value area percent" = 70);
def showPointOfControl = yes;
def showValueArea = no;
plot MB = if plotsDomain then mbar else Double.NaN;
plot ProfileHigh = if plotsDomain then hProfile else Double.NaN;
plot ProfileLow = if plotsDomain then lProfile else Double.NaN;
plot PGHigh = if plotsDomain then hPG else Double.NaN;
plot PGLow = if plotsDomain then lPG else Double.NaN;

DefineGlobalColor("Monkey Bar", GetColor(4));
DefineGlobalColor("The Playground", GetColor(3));
DefineGlobalColor("Open Price", GetColor(1));
DefineGlobalColor("Close Price", GetColor(1));
DefineGlobalColor("Volume", GetColor(8));
DefineGlobalColor("Volume Value Area", GetColor(2));
DefineGlobalColor("Volume Point of Control", GetColor(3));
DefineGlobalColor("Initial Balance", GetColor(7));
DefineGlobalColor("Profiles", GetColor(1));
tpo.Show(GlobalColor("Profiles"), if showPointOfControl
                                 then GlobalColor("Volume Point Of Control")
                                 else Color.CURRENT,
                                 if showValueArea
                                 then GlobalColor("Volume Value Area")
                                 else Color.CURRENT, opacity);
MB.SetDefaultColor(GlobalColor("Monkey Bar"));
MB.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PGHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PGLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PGHigh.SetDefaultColor(GlobalColor("The Playground"));
PGLow.SetDefaultColor(GlobalColor("The Playground"));
ProfileHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
ProfileLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
ProfileHigh.SetDefaultColor(GetColor(3));
ProfileLow.SetDefaultColor(GetColor(3));
ProfileHigh.Hide();
ProfileLow.Hide();
# End Code TPO Refined

TPO (Time Price Opportunity) - User can choose time segments beginning at RTH Open

RxAEF5w.png


Code:
# TPO Per User Time Segment Starting at RTH
# Mobius
# Chat Room Request 03.29.2018

input pricePerRowHeightMode = {AUTOMATIC, TICKSIZE, default CUSTOM};
input customRowHeight = 1.0;
input timePerProfile = {CHART, default MINUTE, HOUR, DAY, WEEK, MONTH, "OPT EXP", BAR};
input multiplier = 1;
input onExpansion = no;
input profiles = 10;
input showPointOfControl = yes;
input showValueArea = yes;
input valueAreaPercent = 70;
input opacity = 7;
input Minutes = 60;

def period;
def yyyymmdd = getYyyyMmDd();
def seconds = secondsFromTime(0);
def month = getYear() * 12 + getMonth();
def day_number = daysFromDate(first(yyyymmdd)) + getDayOfWeek(first(yyyymmdd));
def dom = getDayOfMonth(yyyymmdd);
def dow = getDayOfWeek(yyyymmdd - dom + 1);
def expthismonth = (if dow > 5 then 27 else 20) - dow;
def exp_opt = month + (dom > expthismonth);
switch (timePerProfile) {
case CHART:
    period = 0;
case MINUTE:
    period = floor(seconds / 60 + day_number * 24 * 60);
case HOUR:
    period = floor(seconds / 3600 + day_number * 24);
case DAY:
    period = countTradingDays(Min(first(yyyymmdd), yyyymmdd), yyyymmdd) - 1;
case WEEK:
    period = floor(day_number / 7);
case MONTH:
    period = floor(month - first(month));
case "OPT EXP":
    period = exp_opt - first(exp_opt);
case BAR:
    period = barNumber() - 1;
}

input RthBegin  = 0930;
input RthEnd    = 1600;
#input showBubbles = no;

def bar = BarNumber();
def RTHBar1 = if SecondsFromTime(RthBegin) == 0 and
                 SecondsTillTime(RthBegin) == 0
              then bar
              else RTHBar1[1];
def RTHBarEnd = if SecondsFromTime(RthEnd) == 0 and
                   SecondsTillTime(RthEnd) == 0
                then 1
                else Double.NaN;
def RTH = SecondsFromTime(RthBegin) > 0 and
          SecondsTillTime(RthEnd) > 0;
def start_t = if RTH and !RTH[1]
              then getTime()
              else Start_t[1];
def t = if start_t == getTime()
        then 1
        else getTime() % (Minutes * 60 * 1000) == 0;
def cond = t;
def height;
switch (pricePerRowHeightMode) {
case AUTOMATIC:
    height = PricePerRow.AUTOMATIC;
case TICKSIZE:
    height = PricePerRow.TICKSIZE;
case CUSTOM:
    height = customRowHeight;
}

profile tpo = timeProfile("startNewProfile" = cond, "onExpansion" = onExpansion, "numberOfProfiles" = profiles, "pricePerRow" = height, "value area percent" = valueAreaPercent);
def con = compoundValue(1, onExpansion, no);
def pc = if IsNaN(tpo.getPointOfControl()) and con then pc[1] else tpo.getPointOfControl();
def hVA = if IsNaN(tpo.getHighestValueArea()) and con then hVA[1] else tpo.getHighestValueArea();
def lVA = if IsNaN(tpo.getLowestValueArea()) and con then lVA[1] else tpo.getLowestValueArea();

def hProfile = if IsNaN(tpo.getHighest()) and con then hProfile[1] else tpo.getHighest();
def lProfile = if IsNaN(tpo.getLowest()) and con then lProfile[1] else tpo.getLowest();
def plotsDomain = IsNaN(close) == onExpansion;

plot POC = if plotsDomain then pc else Double.NaN;
plot ProfileHigh = if plotsDomain then hProfile else Double.NaN;
plot ProfileLow = if plotsDomain then lProfile else Double.NaN;
plot VAHigh = if plotsDomain then hVA else Double.NaN;
plot VALow = if plotsDomain then lVA else Double.NaN;

DefineGlobalColor("Profile", GetColor(1));
DefineGlobalColor("Point Of Control", GetColor(5));
DefineGlobalColor("Value Area", GetColor(8));

tpo.show(globalColor("Profile"), if showPointOfControl then globalColor("Point Of Control") else color.current, if showValueArea then globalColor("Value Area") else color.current, opacity);
POC.SetDefaultColor(globalColor("Point Of Control"));
POC.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
VAHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
VALow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
VAHigh.SetDefaultColor(globalColor("Value Area"));
VALow.SetDefaultColor(globalColor("Value Area"));
ProfileHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
ProfileLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
ProfileHigh.SetDefaultColor(GetColor(3));
ProfileLow.SetDefaultColor(GetColor(3));
ProfileHigh.hide();
ProfileLow.hide();
# End Code TPO Per User Time Segment

TPO scanner by BLT: https://tos.mx/TwmYTE
 
Last edited by a moderator:

mc01439

Well-known member
2019 Donor
VIP
Took a look at the TPO you uploaded today. Will need to watch for a bit during open hours before I can comment. Have never traded this before but always willing to look at anything if it can help improve my edge. Thank you for sharing.
 

horserider

Well-known member
VIP
The fun thing about these is if price has 2 closes above or below a VAL there is a very good chance it will continue to the opposite VAL. Check the VAL difference to see how much profit might be available.

This one is a Time Profile Line and will be very near the POC which is price based. I think technically the POC is said to be more accurate. For our trading I doubt it makes any difference.
 

DadWolf11

New member
Long time lurker, but wanted to say I really appreciate this site and all of the members here.

Question: Is there a way to configure Volume Profile to display only the Globex overnight session?

Ideally, I would like to have 2 Volume Profile studies on the same chart. One for the night and day sessions separated.

All the best,
J
 

BenTen

Administrative
Staff member
Staff
VIP
Hmm. I'm not sure. But maybe you can try to implement some sort of time limit into the Volume Profile indicator?
 

DadWolf11

New member
Hmm. I'm not sure. But maybe you can try to implement some sort of time limit into the Volume Profile indicator?
Thank you for pointing me in the right direction, sir.

I think I've got an idea of how to do it lol, I can't seem to figure out how to isolate the time period from 3p pst to 6:30a pst following day to implement within the volume profile period
 

adii800

Member
I was looking for the same function as Im getting into TPO and Volume Profiles more on TOS, consider using the SecondsFromTime() function.
I would appreciate any updates :)
 
Last edited:

DadWolf11

New member
I was looking for the same function as Im getting into TPO and Volume Profiles more on TOS, consider using the SecondsFromTime() function.
I would appreciate any updates :)
Hi, try this:

Code:
input pricePerRowHeightMode = {AUTOMATIC, TICKSIZE, default CUSTOM};

input customRowHeight = 1.0;

input timePerProfile = {CHART, default MINUTE, HOUR, DAY, WEEK, MONTH, "OPT EXP", BAR};

input multiplier = 1;

input onExpansion = no;

input profiles = 1;

input showPointOfControl = yes;

input showValueArea = yes;

input valueAreaPercent = 70;

input opacity = 7;



def period;

def yyyymmdd = getYyyyMmDd();

def seconds = secondsFromTime(0);

def month = getYear() * 12 + getMonth();

def day_number = daysFromDate(first(yyyymmdd)) + getDayOfWeek(first(yyyymmdd));

def dom = getDayOfMonth(yyyymmdd);

def dow = getDayOfWeek(yyyymmdd - dom + 1);

def expthismonth = (if dow > 5 then 27 else 20) - dow;

def exp_opt = month + (dom > expthismonth);

switch (timePerProfile) {

case CHART:

period = 0;

case MINUTE:

period = floor(seconds / 60 + day_number * 24 * 60);

case HOUR:

period = floor(seconds / 3600 + day_number * 24);

case DAY:

period = countTradingDays(Min(first(yyyymmdd), yyyymmdd), yyyymmdd) - 1;

case WEEK:

period = floor(day_number / 7);

case MONTH:

period = floor(month - first(month));

case "OPT EXP":

period = exp_opt - first(exp_opt);

case BAR:

period = barNumber() - 1;

}



input RthBegin  = 0930;

input RthEnd    = 1600;

#input showBubbles = no;



def bar = BarNumber();

def RTHBar1 = if SecondsFromTime(RthBegin) == 0 and

SecondsTillTime(RthBegin) == 0

then bar

else RTHBar1[1];

def RTHBarEnd = if SecondsFromTime(RthEnd) == 0 and

SecondsTillTime(RthEnd) == 0

then 1

else Double.NaN;

def RTH = SecondsFromTime(RthBegin) > 0 and

SecondsTillTime(RthEnd) > 0;

def cond = RTH != RTH[1];

def height;

switch (pricePerRowHeightMode) {

case AUTOMATIC:

height = PricePerRow.AUTOMATIC;

case TICKSIZE:

height = PricePerRow.TICKSIZE;

case CUSTOM:

height = customRowHeight;

}



profile tpo = timeProfile("startNewProfile" = cond, "onExpansion" = onExpansion, "numberOfProfiles" = profiles, "pricePerRow" = height, "value area percent" = valueAreaPercent);

def con = compoundValue(1, onExpansion, no);

def pc = if IsNaN(tpo.getPointOfControl()) and con then pc[1] else tpo.getPointOfControl();

def hVA = if IsNaN(tpo.getHighestValueArea()) and con then hVA[1] else tpo.getHighestValueArea();

def lVA = if IsNaN(tpo.getLowestValueArea()) and con then lVA[1] else tpo.getLowestValueArea();



def hProfile = if IsNaN(tpo.getHighest()) and con then hProfile[1] else tpo.getHighest();

def lProfile = if IsNaN(tpo.getLowest()) and con then lProfile[1] else tpo.getLowest();

def plotsDomain = IsNaN(close) == onExpansion;



plot POC = if plotsDomain then pc else Double.NaN;

plot ProfileHigh = if plotsDomain then hProfile else Double.NaN;

plot ProfileLow = if plotsDomain then lProfile else Double.NaN;

plot VAHigh = if plotsDomain then hVA else Double.NaN;

plot VALow = if plotsDomain then lVA else Double.NaN;



DefineGlobalColor("Profile", GetColor(1));

DefineGlobalColor("Point Of Control", GetColor(5));

DefineGlobalColor("Value Area", GetColor(8));



tpo.show(globalColor("Profile"), if showPointOfControl then globalColor("Point Of Control") else color.current, if showValueArea then globalColor("Value Area") else color.current, opacity);

POC.SetDefaultColor(globalColor("Point Of Control"));

POC.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

VAHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

VALow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

VAHigh.SetDefaultColor(globalColor("Value Area"));

VALow.SetDefaultColor(globalColor("Value Area"));

ProfileHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

ProfileLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

ProfileHigh.SetDefaultColor(GetColor(3));

ProfileLow.SetDefaultColor(GetColor(3));

ProfileHigh.hide();

ProfileLow.hide();
 

Tony46

New member
I need the indicators of the pervious session, weeks or mouth to be drawn on the current session ,week, month. Like in the indicator "previous day High/Low/Close".

I enabled Money Bars chart on ThinkorSwim:
  1. Go to chart settings
  2. Click on Appearance
  3. Under Chart Mode, select Money Bars
Example: Monkey Bars

AqcdWqW.png


Showing previous day High/Low/Close

cyTWl2j.png


Indicator previous day High/Low/Close, draws lines on the chart previous day High/Low/Close for the current session. I want the same actions from indicator Monkey Bars, its values ( Point of Control , PGHigh, PGLow,Monkey Bar) from previous month draws lines on the chart for the current month. I look smaller time frame and I want to see where the price towards the values indicator Monkey Bars from last month, if possible. I am drawing them myself now using horizontal lines, but it takes a long time and is very inconvenient.

Sorry for my English I don't speak it.
 

XeoNoX

Well-known member
VIP
Due to limitations in the code because TDAmeritrade only has it referenced, certain plots cant be defined without the source code for the defined function. if you have the complete source for monkeybars it would be possible to accomplish what you want without limitations.

Below is the best that i could figure out how to do without the complete source.

Change the input "displace" to the number of bars in the intraday, 78 is 5 minute chart. 10 mins would be 39, etc.

7tTdMEM.png


Code:
#
# TD Ameritrade IP Company, Inc. (c) 2010-2020
#
input displace = 78;
input pricePerRowHeightMode = {default AUTOMATIC, TICKSIZE, CUSTOM};
input customRowHeight = 1.0;
input aggregationPeriod = {"1 min", "2 min", "3 min", "4 min", "5 min", "10 min", "15 min", "20 min", default "30 min", "1 hour", "2 hours", "4 hours", "Day", "2 Days", "3 Days", "4 Days", "Week", "Month", "Quarter", "Year"};
input timePerProfile = {default CHART, MINUTE, HOUR, DAY, WEEK, MONTH, "OPT EXP", BAR, YEAR};
input multiplier = 1;
input onExpansion = yes;
input profiles = 1000;
input showMonkeyBar = yes;
input showThePlayground = yes;
input thePlaygroundPercent = 70;
input opacity = 100;
input emphasizeFirstDigit = no;
input markOpenPrice = yes;
input markClosePrice = yes;
input volumeShowStyle = MonkeyVolumeShowStyle.NONE;
input showVolumeVA = yes;
input showVolumePoc = yes;
input theVolumePercent = 70;
input showInitialBalance = yes;
input initialBalanceRange = 3;

def period;
def yyyymmdd = getYyyyMmDd();
def seconds = secondsFromTime(0);
def year = getYear();
def month = year * 12 + getMonth();
def day_number = daysFromDate(first(yyyymmdd)) + getDayOfWeek(first(yyyymmdd));
def dom = getDayOfMonth(yyyymmdd);
def dow = getDayOfWeek(yyyymmdd - dom + 1);
def expthismonth = (if dow > 5 then 27 else 20) - dow;
def exp_opt = month + (dom > expthismonth);
def periodMin = Floor(seconds / 60 + day_number * 24 * 60);
def periodHour = Floor(seconds / 3600 + day_number * 24);
def periodDay = countTradingDays(Min(first(yyyymmdd), yyyymmdd), yyyymmdd) - 1;
def periodWeek = Floor(day_number / 7);
def periodMonth = month - first(month);
def periodQuarter = Ceil(month / 3) - first(Ceil(month / 3));
def periodYear = year - first(year);

switch (timePerProfile) {
case CHART:
    period = 0;
case MINUTE:
    period = periodMin;
case HOUR:
    period = periodHour;
case DAY:
    period = periodDay;
case WEEK:
    period = periodWeek;
case MONTH:
    period = periodMonth;
case "OPT EXP":
    period = exp_opt - first(exp_opt);
case BAR:
    period = barNumber() - 1;
case YEAR:
    period = periodYear;
}

def count = compoundvalue(1, if period != period[1] then (getValue(count, 1) + period - period[1]) % multiplier else getValue(count, 1), 0);
def cond = compoundvalue(1, count < count[1] + period - period[1], yes);
def height;
switch (pricePerRowHeightMode) {
case AUTOMATIC:
    height = PricePerRow.AUTOMATIC;
case TICKSIZE:
    height = PricePerRow.TICKSIZE;
case CUSTOM:
    height = customRowHeight;
}

def timeInterval;
def aggMultiplier;
switch (aggregationPeriod) {
case "1 min":
    timeInterval = periodMin;
    aggMultiplier = 1;
case "2 min":
    timeInterval = periodMin;
    aggMultiplier = 2;
case "3 min":
    timeInterval = periodMin;
    aggMultiplier = 3;
case "4 min":
    timeInterval = periodMin;
    aggMultiplier = 4;
case "5 min":
    timeInterval = periodMin;
    aggMultiplier = 5;
case "10 min":
    timeInterval = periodMin;
    aggMultiplier = 10;
case "15 min":
    timeInterval = periodMin;
    aggMultiplier = 15;
case "20 min":
    timeInterval = periodMin;
    aggMultiplier = 20;
case "30 min":
    timeInterval = periodMin;
    aggMultiplier = 30;
case "1 hour":
    timeInterval = periodHour;
    aggMultiplier = 1;
case "2 hours":
    timeInterval = periodHour;
    aggMultiplier = 2;
case "4 hours":
    timeInterval = periodHour;
    aggMultiplier = 4;
case "Day":
    timeInterval = periodDay;
    aggMultiplier = 1;
case "2 Days":
    timeInterval = periodDay;
    aggMultiplier = 2;
case "3 Days":
    timeInterval = periodDay;
    aggMultiplier = 3;
case "4 Days":
    timeInterval = periodDay;
    aggMultiplier = 4;
case "Week":
    timeInterval = periodWeek;
    aggMultiplier = 1;
case "Month":
    timeInterval = periodMonth;
    aggMultiplier = 1;
case "Quarter":
    timeInterval = periodQuarter;
    aggMultiplier = 1;
case "Year":
    timeInterval = periodYear;
    aggMultiplier = 1;
}

def agg_count = compoundvalue(1, if timeInterval != timeInterval[1] then (getValue(agg_count, 1) + timeInterval - timeInterval[1]) % aggMultiplier else getValue(agg_count, 1), 0);
def agg_cond = compoundvalue(1,  agg_count < agg_count[1] + timeInterval - timeInterval[1], yes);

def digit = compoundValue(1, if cond then 1 else agg_cond + getValue(digit, 1), 1);

profile monkey = monkeyBars(digit, "startNewProfile" = cond, "onExpansion" = onExpansion,
"numberOfProfiles" = profiles, "pricePerRow" = height, "the playground percent" = thePlaygroundPercent,
"emphasize first digit" = emphasizeFirstDigit, "volumeProfileShowStyle" = volumeShowStyle, "volumePercentVA" = theVolumePercent,
 "show initial balance" = showInitialBalance, "initial balance range" = initialBalanceRange);
def con = compoundValue(1, onExpansion, no);
def mbar = compoundvalue(1, if IsNaN(monkey.getPointOfControl()) and con then getValue(mbar, 1) else monkey.getPointOfControl(), monkey.getPointOfControl());
def hPG = compoundvalue(1, if IsNaN(monkey.getHighestValueArea()) and con then getValue(hPG, 1) else monkey.getHighestValueArea(), monkey.getHighestValueArea());
def lPG = compoundvalue(1, if IsNaN(monkey.getLowestValueArea()) and con then getValue(lPG, 1) else monkey.getLowestValueArea(), monkey.getLowestValueArea());

def hProfile = compoundvalue(1, if IsNaN(monkey.getHighest()) and con then getValue(hProfile, 1) else monkey.getHighest(), monkey.getHighest());
def lProfile = compoundvalue(1, if IsNaN(monkey.getLowest()) and con then getValue(lProfile, 1) else monkey.getLowest(), monkey.getLowest());
def plotsDomain = IsNaN(close) == onExpansion;

plot MB = if plotsDomain then mbar[displace] else Double.NaN;
plot ProfileHigh = if plotsDomain then hProfile[displace] else Double.NaN;
plot ProfileLow = if plotsDomain then lProfile[displace] else Double.NaN;
plot PGHigh = if plotsDomain then hPG[displace] else Double.NaN;
plot PGLow = if plotsDomain then lPG[displace] else Double.NaN;


DefineGlobalColor("Monkey Bar", GetColor(4));
DefineGlobalColor("The Playground", GetColor(3));
DefineGlobalColor("Open Price", GetColor(1));
DefineGlobalColor("Close Price", GetColor(1));
DefineGlobalColor("Volume", GetColor(8));
DefineGlobalColor("Volume Value Area", GetColor(2));
DefineGlobalColor("Volume Point of Control", GetColor(3));
DefineGlobalColor("Initial Balance", GetColor(7));

monkey.show(color.red, if showMonkeyBar then globalColor("Monkey Bar") else color.current,
 if showThePlayground then globalColor("The Playground") else color.current,
 opacity, if markOpenPrice then globalColor("Open Price") else color.current,
 if markClosePrice then globalColor("Close Price") else color.current,
 if showInitialBalance then globalColor("Initial Balance") else color.current,
 globalColor("Volume"),
 if showVolumeVA then globalColor("Volume Value Area") else color.current,
 if showVolumePOC then globalColor("Volume Point of Control") else color.current);
MB.SetDefaultColor(globalColor("Monkey Bar"));
MB.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PGHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PGLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
PGHigh.SetDefaultColor(globalColor("The Playground"));
PGLow.SetDefaultColor(globalColor("The Playground"));
ProfileHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
ProfileLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
ProfileHigh.SetDefaultColor(GetColor(3));
ProfileLow.SetDefaultColor(GetColor(3));
ProfileHigh.hide();
ProfileLow.hide();
 

marlonbrando

New member
Ive been a "long time lurker" here. Learned a lot and developed a couple indicators based off of others, learned some basic thinkscript coding. However, I was wondering if it were even possible to write a script to auto plot TD's monkey bars (TPO, market profile, whatever you choose to call it) single prints. I trade based off of price action at single prints that clearly define buyer / seller levels, and generally simplifies the "auction" concept of the market. This strategy has been highly effective trading futures over the past year when I first started using profile only and rvol, rather than multiple indicators.

I spend WAY too much time manually plotting these single print levels in profile. If it is possible, I can spend the time to develop thinkscript for this. If anyone is interested in working on it together, feel free to reach out. If we can make this happen, I would like to share it to the forum. It would be nice to give back after learning so much about thinkscript here in the past. Thanks fellas!
 

halcyonguy

Well-known member
VIP
i am curious about this, but admit i know nothing about monkey bars, nor any of the terms. i don't understand what the digits represent. i don't know what single prints are.

i read this, but it didn't help me. i'm a visual guy and sometimes need to see marked up pictures, to help explain a topic.
https://tlc.thinkorswim.com/center/howToTos/thinkManual/charts/Chart-Modes/monkeybars

1. i don't understand this,
... manually plotting these single print levels in profile.

2. are the rows of numbers on a monkey bar chart similar to a volume profile layout? it is possible to plot a profile on variables other than volume.

3. do you want a study to draw things on a candle chart or a monkey chart?
 

marlonbrando

New member
i am curious about this, but admit i know nothing about monkey bars, nor any of the terms. i don't understand what the digits represent. i don't know what single prints are.

i read this, but it didn't help me. i'm a visual guy and sometimes need to see marked up pictures, to help explain a topic.
https://tlc.thinkorswim.com/center/howToTos/thinkManual/charts/Chart-Modes/monkeybars

1. i don't understand this,
... manually plotting these single print levels in profile.

2. are the rows of numbers on a monkey bar chart similar to a volume profile layout? it is possible to plot a profile on variables other than volume.

3. do you want a study to draw things on a candle chart or a monkey chart?
hey, thanks for the response. I'll do my best to answer your questions and ill attach a screenshot of what im plotting manually

1. I layer profile behind 3 min candles on an intraday chart via thinkorswim 'monkey bar' study, which allows you to see price action printing on both candles and profile.

2. the rows of numbers are the same thing as volume profile layout, except monkey bars (more commonly known as TPO, or time price opportunity) show profile of time spent at a particular price. When you look at these two, generally they match up pretty well. I just think TPO is more precise, given it uses time rather than volume. Volume has mattered a little less to me, since I've found that a 50 day rvol that is high just tells me theres good enough volume to get in on a trade-- thats a whole different topic so ill move on

3. the study should plot levels where the single prints begin and end. check the screenshots to get an idea of what I mean. A single print is just that, a single layer of prints, where price zips through. most times this helps you identify buyer seller levels since price fails to accept in these areas, and moves to a level of acceptance. with TPO (or in this case, with thinkorswim, Monkey Bars) youll have the point of control at the point that price spent the most time. In this case it would be intraday. The numbers are just 'periods'. Mine are set to 30 min periods. I dont look at the numbers either, I can tell different periods by color in the example posted below.

Single prints - /NQ 11/4/21
 

MerryDay

Administrative
Staff member
Staff
VIP
hey, thanks for the response. I'll do my best to answer your questions and ill attach a screenshot of what im plotting manually

1. I layer profile behind 3 min candles on an intraday chart via thinkorswim 'monkey bar' study, which allows you to see price action printing on both candles and profile.

2. the rows of numbers are the same thing as volume profile layout, except monkey bars (more commonly known as TPO, or time price opportunity) show profile of time spent at a particular price. When you look at these two, generally they match up pretty well. I just think TPO is more precise, given it uses time rather than volume. Volume has mattered a little less to me, since I've found that a 50 day rvol that is high just tells me theres good enough volume to get in on a trade-- thats a whole different topic so ill move on

3. the study should plot levels where the single prints begin and end. check the screenshots to get an idea of what I mean. A single print is just that, a single layer of prints, where price zips through. most times this helps you identify buyer seller levels since price fails to accept in these areas, and moves to a level of acceptance. with TPO (or in this case, with thinkorswim, Monkey Bars) youll have the point of control at the point that price spent the most time. In this case it would be intraday. The numbers are just 'periods'. Mine are set to 30 min periods. I dont look at the numbers either, I can tell different periods by color in the example posted below.

Single prints - /NQ 11/4/21
@marlonbrando I moved your post here as this thread has been consolidated to contain all the information the forum has on TPO Monkey Bars.
Start with the 1st post and read through to what other members have done.
 

Similar threads

Top