Trend Multi Timeframe Indicator for MACD on ThinkorSwim

S

stocksniper

New member
Does anyone have a multi time frame MacD indicator similar to this EMA trend indicator below, or can this one be changed to macd. I think a lot of traders would like it. Thanks guys!

Code:
input MAtype = AverageType.EXPONENTIAL;
input ShortAverage = 5;
input LongAverage = 21;

def MA_month_close;
def MA_month_shortAvg;
def MA_month_longAvg;
def MA_month_higher;
def MA_month_lower;
def MA_month_same;
def MA_month_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.MONTH {
    MA_month_close = close(period="Month");
    MA_month_shortAvg = MovingAverage(MAtype, MA_month_close, ShortAverage);
    MA_month_longAvg = MovingAverage(MAtype,MA_month_close, LongAverage);
    MA_month_nowcrossing = if Crosses(MA_month_shortAvg, MA_month_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_month_same = if MA_month_nowcrossing == 1 then 1 else Double.NaN;
    if MA_month_same == 1 {
        MA_month_higher = Double.NaN;
        MA_month_lower = Double.NaN;
    } else {
        MA_month_higher = if MA_month_shortAvg >= MA_month_longAvg[1] then 1 else Double.NaN;
        MA_month_lower = if MA_month_shortAvg < MA_month_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_month_close = 0;
    MA_month_shortAvg = 0;
    MA_month_longAvg = 0;
    MA_month_higher = Double.NaN;
    MA_month_lower = Double.NaN;
    MA_month_same = Double.NaN;
    MA_month_nowcrossing = 0;
}
AddLabel(MA_month_higher, "M", Color.DARK_GREEN);
AddLabel(MA_month_lower, "M", Color.DARK_RED);
AddLabel(MA_month_same, "M", Color.WHITE);

def MA_week_close;
def MA_week_shortAvg;
def MA_week_longAvg;
def MA_week_higher;
def MA_week_lower;
def MA_week_same;
def MA_week_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.WEEK {
    MA_week_close = close(period="Week");
    MA_week_shortAvg = MovingAverage(MAtype, MA_week_close, ShortAverage);
    MA_week_longAvg = MovingAverage(MAtype,MA_week_close, LongAverage);
    MA_week_nowcrossing = if Crosses(MA_week_shortAvg, MA_week_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_week_same = if MA_week_nowcrossing == 1 then 1 else Double.NaN;
    if MA_week_same == 1 {
        MA_week_higher = Double.NaN;
        MA_week_lower = Double.NaN;
    } else {
        MA_week_higher = if MA_week_shortAvg >= MA_week_longAvg[1] then 1 else Double.NaN;
        MA_week_lower = if MA_week_shortAvg < MA_week_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_week_close = 0;
    MA_week_shortAvg = 0;
    MA_week_longAvg = 0;
    MA_week_higher = Double.NaN;
    MA_week_lower = Double.NaN;
    MA_week_same = Double.NaN;
    MA_week_nowcrossing = 0;
}
AddLabel(MA_week_higher, "W", Color.DARK_GREEN);
AddLabel(MA_week_lower, "W", Color.DARK_RED);
AddLabel(MA_week_same, "W", Color.WHITE);

def MA_4day_close;
def MA_4day_shortAvg;
def MA_4day_longAvg;
def MA_4day_higher;
def MA_4day_lower;
def MA_4day_same;
def MA_4day_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.FOUR_DAYS {
    MA_4day_close = close(period="4 days");
    MA_4day_shortAvg = MovingAverage(MAtype, MA_4day_close, ShortAverage);
    MA_4day_longAvg = MovingAverage(MAtype,MA_4day_close, LongAverage);
    MA_4day_nowcrossing = if Crosses(MA_4day_shortAvg, MA_4day_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_4day_same = if MA_4day_nowcrossing == 1 then 1 else Double.NaN;
    if MA_4day_same == 1 {
        MA_4day_higher = Double.NaN;
        MA_4day_lower = Double.NaN;
    } else {
        MA_4day_higher = if MA_4day_shortAvg >= MA_4day_longAvg[1] then 1 else Double.NaN;
        MA_4day_lower = if MA_4day_shortAvg < MA_4day_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_4day_close = 0;
    MA_4day_shortAvg = 0;
    MA_4day_longAvg = 0;
    MA_4day_higher = Double.NaN;
    MA_4day_lower = Double.NaN;
    MA_4day_same = Double.NaN;
    MA_4day_nowcrossing = 0;
}
AddLabel(MA_4day_higher, "4D", Color.DARK_GREEN);
AddLabel(MA_4day_lower, "4D", Color.DARK_RED);
AddLabel(MA_4day_same, "4D", Color.WHITE);

def MA_3day_close;
def MA_3day_shortAvg;
def MA_3day_longAvg;
def MA_3day_higher;
def MA_3day_lower;
def MA_3day_same;
def MA_3day_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.THREE_DAYS {
    MA_3day_close = close(period="3 days");
    MA_3day_shortAvg = MovingAverage(MAtype, MA_3day_close, ShortAverage);
    MA_3day_longAvg = MovingAverage(MAtype,MA_3day_close, LongAverage);
    MA_3day_nowcrossing = if Crosses(MA_3day_shortAvg, MA_3day_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_3day_same = if MA_3day_nowcrossing == 1 then 1 else Double.NaN;
    if MA_3day_same == 1 {
        MA_3day_higher = Double.NaN;
        MA_3day_lower = Double.NaN;
    } else {
        MA_3day_higher = if MA_3day_shortAvg >= MA_3day_longAvg[1] then 1 else Double.NaN;
        MA_3day_lower = if MA_3day_shortAvg < MA_3day_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_3day_close = 0;
    MA_3day_shortAvg = 0;
    MA_3day_longAvg = 0;
    MA_3day_higher = Double.NaN;
    MA_3day_lower = Double.NaN;
    MA_3day_same = Double.NaN;
    MA_3day_nowcrossing = 0;
}
AddLabel(MA_3day_higher, "3D", Color.DARK_GREEN);
AddLabel(MA_3day_lower, "3D", Color.DARK_RED);
AddLabel(MA_3day_same, "3D", Color.WHITE);

def MA_2day_close;
def MA_2day_shortAvg;
def MA_2day_longAvg;
def MA_2day_higher;
def MA_2day_lower;
def MA_2day_same;
def MA_2day_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.TWO_DAYS {
    MA_2day_close = close(period="2 days");
    MA_2day_shortAvg = MovingAverage(MAtype, MA_2day_close, ShortAverage);
    MA_2day_longAvg = MovingAverage(MAtype,MA_2day_close, LongAverage);
    MA_2day_nowcrossing = if Crosses(MA_2day_shortAvg, MA_2day_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_2day_same = if MA_2day_nowcrossing == 1 then 1 else Double.NaN;
    if MA_2day_same == 1 {
        MA_2day_higher = Double.NaN;
        MA_2day_lower = Double.NaN;
    } else {
        MA_2day_higher = if MA_2day_shortAvg >= MA_2day_longAvg[1] then 1 else Double.NaN;
        MA_2day_lower = if MA_2day_shortAvg < MA_2day_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_2day_close = 0;
    MA_2day_shortAvg = 0;
    MA_2day_longAvg = 0;
    MA_2day_higher = Double.NaN;
    MA_2day_lower = Double.NaN;
    MA_2day_same = Double.NaN;
    MA_2day_nowcrossing = 0;
}
AddLabel(MA_2day_higher, "2D", Color.DARK_GREEN);
AddLabel(MA_2day_lower, "2D", Color.DARK_RED);
AddLabel(MA_2day_same, "2D", Color.WHITE);

def MA_1day_close;
def MA_1day_shortAvg;
def MA_1day_longAvg;
def MA_1day_higher;
def MA_1day_lower;
def MA_1day_same;
def MA_1day_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.DAY {
    MA_1day_close = close(period="Day");
    MA_1day_shortAvg = MovingAverage(MAtype, MA_1day_close, ShortAverage);
    MA_1day_longAvg = MovingAverage(MAtype,MA_1day_close, LongAverage);
    MA_1day_nowcrossing = if Crosses(MA_1day_shortAvg, MA_1day_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_1day_same = if MA_1day_nowcrossing == 1 then 1 else Double.NaN;
    if MA_1day_same == 1 {
        MA_1day_higher = Double.NaN;
        MA_1day_lower = Double.NaN;
    } else {
        MA_1day_higher = if MA_1day_shortAvg >= MA_1day_longAvg[1] then 1 else Double.NaN;
        MA_1day_lower = if MA_1day_shortAvg < MA_1day_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_1day_close = 0;
    MA_1day_shortAvg = 0;
    MA_1day_longAvg = 0;
    MA_1day_higher = Double.NaN;
    MA_1day_lower = Double.NaN;
    MA_1day_same = Double.NaN;
    MA_1day_nowcrossing = 0;
}
AddLabel(MA_1day_higher, "1D", Color.DARK_GREEN);
AddLabel(MA_1day_lower, "1D", Color.DARK_RED);
AddLabel(MA_1day_same, "1D", Color.WHITE);

def MA_4hour_close;
def MA_4hour_shortAvg;
def MA_4hour_longAvg;
def MA_4hour_higher;
def MA_4hour_lower;
def MA_4hour_same;
def MA_4hour_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.FOUR_HOURS {
    MA_4hour_close = close(period="4 hours");
    MA_4hour_shortAvg = MovingAverage(MAtype, MA_4hour_close, ShortAverage);
    MA_4hour_longAvg = MovingAverage(MAtype,MA_4hour_close, LongAverage);
    MA_4hour_nowcrossing = if Crosses(MA_4hour_shortAvg, MA_4hour_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_4hour_same = if MA_4hour_nowcrossing == 1 then 1 else Double.NaN;
    if MA_4hour_same == 1 {
        MA_4hour_higher = Double.NaN;
        MA_4hour_lower = Double.NaN;
    } else {
        MA_4hour_higher = if MA_4hour_shortAvg >= MA_4hour_longAvg[1] then 1 else Double.NaN;
        MA_4hour_lower = if MA_4hour_shortAvg < MA_4hour_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_4hour_close = 0;
    MA_4hour_shortAvg = 0;
    MA_4hour_longAvg = 0;
    MA_4hour_higher = Double.NaN;
    MA_4hour_lower = Double.NaN;
    MA_4hour_same = Double.NaN;
    MA_4hour_nowcrossing = 0;
}
AddLabel(MA_4hour_higher, "4h", Color.DARK_GREEN);
AddLabel(MA_4hour_lower, "4h", Color.DARK_RED);
AddLabel(MA_4hour_same, "4h", Color.WHITE);

def MA_2hour_close;
def MA_2hour_shortAvg;
def MA_2hour_longAvg;
def MA_2hour_higher;
def MA_2hour_lower;
def MA_2hour_same;
def MA_2hour_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.TWO_HOURS {
    MA_2hour_close = close(period="2 hours");
    MA_2hour_shortAvg = MovingAverage(MAtype, MA_2hour_close, ShortAverage);
    MA_2hour_longAvg = MovingAverage(MAtype,MA_2hour_close, LongAverage);
    MA_2hour_nowcrossing = if Crosses(MA_2hour_shortAvg, MA_2hour_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_2hour_same = if MA_2hour_nowcrossing == 1 then 1 else Double.NaN;
    if MA_2hour_same == 1 {
        MA_2hour_higher = Double.NaN;
        MA_2hour_lower = Double.NaN;
    } else {
        MA_2hour_higher = if MA_2hour_shortAvg >= MA_2hour_longAvg[1] then 1 else Double.NaN;
        MA_2hour_lower = if MA_2hour_shortAvg < MA_2hour_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_2hour_close = 0;
    MA_2hour_shortAvg = 0;
    MA_2hour_longAvg = 0;
    MA_2hour_higher = Double.NaN;
    MA_2hour_lower = Double.NaN;
    MA_2hour_same = Double.NaN;
    MA_2hour_nowcrossing = 0;
}
AddLabel(MA_2hour_higher, "2h", Color.DARK_GREEN);
AddLabel(MA_2hour_lower, "2h", Color.DARK_RED);
AddLabel(MA_2hour_same, "2h", Color.WHITE);

def MA_1hour_close;
def MA_1hour_shortAvg;
def MA_1hour_longAvg;
def MA_1hour_higher;
def MA_1hour_lower;
def MA_1hour_same;
def MA_1hour_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.HOUR {
    MA_1hour_close = close(period="1 hour");
    MA_1hour_shortAvg = MovingAverage(MAtype, MA_1hour_close, ShortAverage);
    MA_1hour_longAvg = MovingAverage(MAtype,MA_1hour_close, LongAverage);
    MA_1hour_nowcrossing = if Crosses(MA_1hour_shortAvg, MA_1hour_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_1hour_same = if MA_1hour_nowcrossing == 1 then 1 else Double.NaN;
    if MA_1hour_same == 1 {
        MA_1hour_higher = Double.NaN;
        MA_1hour_lower = Double.NaN;
    } else {
        MA_1hour_higher = if MA_1hour_shortAvg >= MA_1hour_longAvg[1] then 1 else Double.NaN;
        MA_1hour_lower = if MA_1hour_shortAvg < MA_1hour_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_1hour_close = 0;
    MA_1hour_shortAvg = 0;
    MA_1hour_longAvg = 0;
    MA_1hour_higher = Double.NaN;
    MA_1hour_lower = Double.NaN;
    MA_1hour_same = Double.NaN;
    MA_1hour_nowcrossing = 0;
}
AddLabel(MA_1hour_higher, "1h", Color.DARK_GREEN);
AddLabel(MA_1hour_lower, "1h", Color.DARK_RED);
AddLabel(MA_1hour_same, "1h", Color.WHITE);

def MA_30min_close;
def MA_30min_shortAvg;
def MA_30min_longAvg;
def MA_30min_higher;
def MA_30min_lower;
def MA_30min_same;
def MA_30min_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.THIRTY_MIN {
    MA_30min_close = close(period="30 min");
    MA_30min_shortAvg = MovingAverage(MAtype, MA_30min_close, ShortAverage);
    MA_30min_longAvg = MovingAverage(MAtype,MA_30min_close, LongAverage);
    MA_30min_nowcrossing = if Crosses(MA_30min_shortAvg, MA_30min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_30min_same = if MA_30min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_30min_same == 1 {
        MA_30min_higher = Double.NaN;
        MA_30min_lower = Double.NaN;
    } else {
        MA_30min_higher = if MA_30min_shortAvg >= MA_30min_longAvg[1] then 1 else Double.NaN;
        MA_30min_lower = if MA_30min_shortAvg < MA_30min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_30min_close = 0;
    MA_30min_shortAvg = 0;
    MA_30min_longAvg = 0;
    MA_30min_higher = Double.NaN;
    MA_30min_lower = Double.NaN;
    MA_30min_same = Double.NaN;
    MA_30min_nowcrossing = 0;
}
AddLabel(MA_30min_higher, "30m", Color.DARK_GREEN);
AddLabel(MA_30min_lower, "30m", Color.DARK_RED);
AddLabel(MA_30min_same, "30m", Color.WHITE);

def MA_15min_close;
def MA_15min_shortAvg;
def MA_15min_longAvg;
def MA_15min_higher;
def MA_15min_lower;
def MA_15min_same;
def MA_15min_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.FIFTEEN_MIN {
    MA_15min_close = close(period="15 min");
    MA_15min_shortAvg = MovingAverage(MAtype, MA_15min_close, ShortAverage);
    MA_15min_longAvg = MovingAverage(MAtype,MA_15min_close, LongAverage);
    MA_15min_nowcrossing = if Crosses(MA_15min_shortAvg, MA_15min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_15min_same = if MA_15min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_15min_same == 1 {
        MA_15min_higher = Double.NaN;
        MA_15min_lower = Double.NaN;
    } else {
        MA_15min_higher = if MA_15min_shortAvg >= MA_15min_longAvg[1] then 1 else Double.NaN;
        MA_15min_lower = if MA_15min_shortAvg < MA_15min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_15min_close = 0;
    MA_15min_shortAvg = 0;
    MA_15min_longAvg = 0;
    MA_15min_higher = Double.NaN;
    MA_15min_lower = Double.NaN;
    MA_15min_same = Double.NaN;
    MA_15min_nowcrossing = 0;
}
AddLabel(MA_15min_higher, "15m", Color.DARK_GREEN);
AddLabel(MA_15min_lower, "15m", Color.DARK_RED);
AddLabel(MA_15min_same, "15m", Color.WHITE);

def MA_10min_close;
def MA_10min_shortAvg;
def MA_10min_longAvg;
def MA_10min_higher;
def MA_10min_lower;
def MA_10min_same;
def MA_10min_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.TEN_MIN {
    MA_10min_close = close(period="10 min");
    MA_10min_shortAvg = MovingAverage(MAtype, MA_10min_close, ShortAverage);
    MA_10min_longAvg = MovingAverage(MAtype,MA_10min_close, LongAverage);
    MA_10min_nowcrossing = if Crosses(MA_10min_shortAvg, MA_10min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_10min_same = if MA_10min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_10min_same == 1 {
        MA_10min_higher = Double.NaN;
        MA_10min_lower = Double.NaN;
    } else {
        MA_10min_higher = if MA_10min_shortAvg >= MA_10min_longAvg[1] then 1 else Double.NaN;
        MA_10min_lower = if MA_10min_shortAvg < MA_10min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_10min_close = 0;
    MA_10min_shortAvg = 0;
    MA_10min_longAvg = 0;
    MA_10min_higher = Double.NaN;
    MA_10min_lower = Double.NaN;
    MA_10min_same = Double.NaN;
    MA_10min_nowcrossing = 0;
}
AddLabel(MA_10min_higher, "10m", Color.DARK_GREEN);
AddLabel(MA_10min_lower, "10m", Color.DARK_RED);
AddLabel(MA_10min_same, "10m", Color.WHITE);

def MA_shortAvgmin_close;
def MA_shortAvgmin_shortAvg;
def MA_shortAvgmin_longAvg;
def MA_shortAvgmin_higher;
def MA_shortAvgmin_lower;
def MA_shortAvgmin_same;
def MA_shortAvgmin_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.FIVE_MIN {
    MA_shortAvgmin_close = close(period="5 min");
    MA_shortAvgmin_shortAvg = MovingAverage(MAtype, MA_shortAvgmin_close, ShortAverage);
    MA_shortAvgmin_longAvg = MovingAverage(MAtype,MA_shortAvgmin_close, LongAverage);
    MA_shortAvgmin_nowcrossing = if Crosses(MA_shortAvgmin_shortAvg, MA_shortAvgmin_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_shortAvgmin_same = if MA_shortAvgmin_nowcrossing == 1 then 1 else Double.NaN;
    if MA_shortAvgmin_same == 1 {
        MA_shortAvgmin_higher = Double.NaN;
        MA_shortAvgmin_lower = Double.NaN;
    } else {
        MA_shortAvgmin_higher = if MA_shortAvgmin_shortAvg >= MA_shortAvgmin_longAvg[1] then 1 else Double.NaN;
        MA_shortAvgmin_lower = if MA_shortAvgmin_shortAvg < MA_shortAvgmin_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_shortAvgmin_close = 0;
    MA_shortAvgmin_shortAvg = 0;
    MA_shortAvgmin_longAvg = 0;
    MA_shortAvgmin_higher = Double.NaN;
    MA_shortAvgmin_lower = Double.NaN;
    MA_shortAvgmin_same = Double.NaN;
    MA_shortAvgmin_nowcrossing = 0;
}
AddLabel(MA_shortAvgmin_higher, "5m", Color.DARK_GREEN);
AddLabel(MA_shortAvgmin_lower, "5m", Color.DARK_RED);
AddLabel(MA_shortAvgmin_same, "5m", Color.WHITE);

def MA_4min_close;
def MA_4min_shortAvg;
def MA_4min_longAvg;
def MA_4min_higher;
def MA_4min_lower;
def MA_4min_same;
def MA_4min_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.FOUR_MIN {
    MA_4min_close = close(period="4 min");
    MA_4min_shortAvg = MovingAverage(MAtype, MA_4min_close, ShortAverage);
    MA_4min_longAvg = MovingAverage(MAtype,MA_4min_close, LongAverage);
    MA_4min_nowcrossing = if Crosses(MA_4min_shortAvg, MA_4min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_4min_same = if MA_4min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_4min_same == 1 {
        MA_4min_higher = Double.NaN;
        MA_4min_lower = Double.NaN;
    } else {
        MA_4min_higher = if MA_4min_shortAvg >= MA_4min_longAvg[1] then 1 else Double.NaN;
        MA_4min_lower = if MA_4min_shortAvg < MA_4min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_4min_close = 0;
    MA_4min_shortAvg = 0;
    MA_4min_longAvg = 0;
    MA_4min_higher = Double.NaN;
    MA_4min_lower = Double.NaN;
    MA_4min_same = Double.NaN;
    MA_4min_nowcrossing = 0;
}
AddLabel(MA_4min_higher, "4m", Color.DARK_GREEN);
AddLabel(MA_4min_lower, "4m", Color.DARK_RED);
AddLabel(MA_4min_same, "4m", Color.WHITE);

def MA_3min_close;
def MA_3min_shortAvg;
def MA_3min_longAvg;
def MA_3min_higher;
def MA_3min_lower;
def MA_3min_same;
def MA_3min_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.THREE_MIN {
    MA_3min_close = close(period="3 min");
    MA_3min_shortAvg = MovingAverage(MAtype, MA_3min_close, ShortAverage);
    MA_3min_longAvg = MovingAverage(MAtype,MA_3min_close, LongAverage);
    MA_3min_nowcrossing = if Crosses(MA_3min_shortAvg, MA_3min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_3min_same = if MA_3min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_3min_same == 1 {
        MA_3min_higher = Double.NaN;
        MA_3min_lower = Double.NaN;
    } else {
        MA_3min_higher = if MA_3min_shortAvg >= MA_3min_longAvg[1] then 1 else Double.NaN;
        MA_3min_lower = if MA_3min_shortAvg < MA_3min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_3min_close = 0;
    MA_3min_shortAvg = 0;
    MA_3min_longAvg = 0;
    MA_3min_higher = Double.NaN;
    MA_3min_lower = Double.NaN;
    MA_3min_same = Double.NaN;
    MA_3min_nowcrossing = 0;
}
AddLabel(MA_3min_higher, "3m", Color.DARK_GREEN);
AddLabel(MA_3min_lower, "3m", Color.DARK_RED);
AddLabel(MA_3min_same, "3m", Color.WHITE);

def MA_2min_close;
def MA_2min_shortAvg;
def MA_2min_longAvg;
def MA_2min_higher;
def MA_2min_lower;
def MA_2min_same;
def MA_2min_nowcrossing;
if GetAggregationPeriod() <= AggregationPeriod.TWO_MIN {
    MA_2min_close = close(period="2 min");
    MA_2min_shortAvg = MovingAverage(MAtype, MA_2min_close, ShortAverage);
    MA_2min_longAvg = MovingAverage(MAtype,MA_2min_close, LongAverage);
    MA_2min_nowcrossing = if Crosses(MA_2min_shortAvg, MA_2min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_2min_same = if MA_2min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_2min_same == 1 {
        MA_2min_higher = Double.NaN;
        MA_2min_lower = Double.NaN;
    } else {
        MA_2min_higher = if MA_2min_shortAvg >= MA_2min_longAvg[1] then 1 else Double.NaN;
        MA_2min_lower = if MA_2min_shortAvg < MA_2min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_2min_close = 0;
    MA_2min_shortAvg = 0;
    MA_2min_longAvg = 0;
    MA_2min_higher = Double.NaN;
    MA_2min_lower = Double.NaN;
    MA_2min_same = Double.NaN;
    MA_2min_nowcrossing = 0;
}
AddLabel(MA_2min_higher, "2m", Color.DARK_GREEN);
AddLabel(MA_2min_lower, "2m", Color.DARK_RED);
AddLabel(MA_2min_same, "2m", Color.WHITE);


def MA_1min_close;
def MA_1min_shortAvg;
def MA_1min_longAvg;
def MA_1min_higher;
def MA_1min_lower;
def MA_1min_same;
def MA_1min_nowcrossing;
if GetAggregationPeriod() == AggregationPeriod.MIN {
    MA_1min_close = close(period="1 min");
    MA_1min_shortAvg = MovingAverage(MAtype, MA_1min_close, ShortAverage);
    MA_1min_longAvg = MovingAverage(MAtype,MA_1min_close, LongAverage);
    MA_1min_nowcrossing = if Crosses(MA_1min_shortAvg, MA_1min_longAvg, CrossingDirection.ANY) then 1 else 0;
    MA_1min_same = if MA_1min_nowcrossing == 1 then 1 else Double.NaN;
    if MA_1min_same == 1 {
        MA_1min_higher = Double.NaN;
        MA_1min_lower = Double.NaN;
    } else {
        MA_1min_higher = if MA_1min_shortAvg >= MA_1min_longAvg[1] then 1 else Double.NaN;
        MA_1min_lower = if MA_1min_shortAvg < MA_1min_longAvg[1] then 1 else Double.NaN;
    }
} else {
    MA_1min_close = 0;
    MA_1min_shortAvg = 0;
    MA_1min_longAvg = 0;
    MA_1min_higher = Double.NaN;
    MA_1min_lower = Double.NaN;
    MA_1min_same = Double.NaN;
    MA_1min_nowcrossing = 0;
}
AddLabel(MA_1min_higher, "1m", Color.DARK_GREEN);
AddLabel(MA_1min_lower, "1m", Color.DARK_RED);
AddLabel(MA_1min_same, "1m", Color.WHITE);
 
S

stocksniper

New member
Yes, Is not as easy to read as the one i posted, the one i posted has little blocks with the time frame number and its either green or red, really easy to understand.
 
M

mike101

New member
Hi,

I have code but its not working, it shows me downtrend color, also study is open on small time frame only. It doesnt plot when chart is in 30 mins or 1 hour.

See below attached chart for more info. The study doesnt plot green dots when the MACD is positive.


Code:
#multi time frame MACD

input smallTimeFrame = AggregationPeriod.THREE_MIN; #hint time1:  Plot @ 0.
input MediumTimeFrame = AggregationPeriod.FIVE_MIN; #hint time2:  Plot @ 0.5
input largeTimeFrame = AggregationPeriod.FIFTEEN_MIN; #hint time3:  Plot @ 1.0
input largestTimeFrame = AggregationPeriod.Thirty_MIN; #hint time4:  Plot @ 1.5
#############
declare lower;
input fastLength = 12;
input slowLength = 26;
input MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;
input showBreakoutSingals = no;


def Value1 = MovingAverage(averageType, close(period = smallTimeFrame), fastLength) - MovingAverage(averageType, close(period = smallTimeFrame), slowLength);
def Avg1 = MovingAverage(averageType, Value1, MACDLength);
def Diff1 = Value1 – Avg1;
def ZeroLine1 = 0;

def SmallMACD = if Diff1 > ZeroLine1 then 1 else if Diff1 < ZeroLine1 then -1 else 0;

plot MACD1 = if IsNaN(close) then Double.NaN else 1;
MACD1.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD1.SetLineWeight(2);
DefineGlobalColor("UpTrend", Color.GREEN);
DefineGlobalColor("DownTrend", Color.MAGENTA);
MACD1.AssignValueColor(if SmallMACD > 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));


#Timeframe 2

def Value2 = MovingAverage(averageType, close(period = mediumTimeFrame), fastLength) - MovingAverage(averageType, close(period = mediumTimeFrame), slowLength);
def Avg2 = MovingAverage(averageType, Value2, MACDLength);
def Diff2 = Value2 – Avg2;
def ZeroLine2 = 0;

def MediumMACD = if Diff2 > ZeroLine2 then 1 else if Diff2 < ZeroLine2 then -1 else 0;

plot MACD2 = if IsNaN(close) then Double.NaN else 2;
MACD2.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD2.SetLineWeight(2);
DefineGlobalColor("UpTrend", Color.GREEN);
DefineGlobalColor("DownTrend", Color.MAGENTA);
MACD2.AssignValueColor(if MediumMACD > 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

#Timeframe 3

def Value3 = MovingAverage(averageType, close(period = largeTimeFrame), fastLength) - MovingAverage(averageType,close(period = largeTimeFrame), slowLength);
def Avg3 = MovingAverage(averageType, Value3, MACDLength);
def Diff3 = Value3 – Avg3;
def ZeroLine3 = 0;

def largeMACD = if Diff3 > ZeroLine3 then 1 else if Diff3 < ZeroLine3 then -1 else 0;

plot MACD3 = if IsNaN(close) then Double.NaN else 3;
MACD3.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD3.SetLineWeight(2);
DefineGlobalColor("UpTrend", Color.GREEN);
DefineGlobalColor("DownTrend", Color.MAGENTA);
MACD3.AssignValueColor(if LargeMACD > 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

#Timeframe 4

def Value4 = MovingAverage(averageType, close(period = largestTimeFrame), fastLength) - MovingAverage(averageType,close(period = largestTimeFrame), slowLength);
def Avg4 = MovingAverage(averageType, Value4, MACDLength);
def Diff4 = Value4 – Avg4;
def ZeroLine4 = 0;

def largestMACD = if Diff4 > ZeroLine4 then 1 else if Diff4 < ZeroLine4 then -1 else 0;

plot MACD4 = if IsNaN(close) then Double.NaN else 4;
MACD4.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD4.SetLineWeight(2);
DefineGlobalColor("UpTrend", Color.GREEN);
DefineGlobalColor("DownTrend", Color.MAGENTA);
MACD4.AssignValueColor(if LargestMACD > 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));
any help greatly appreciated.
 
Last edited:
T

tomsk

Well-known member
VIP
Warehouse
@mike101 I have fixed up your code so that the MTF plots properly. Also I have resequenced and cleaned up the code for variables not used as well as utilized more meaningful variable names for any future work you may wish to do. Load this study on a 1 minute chart of AAPL as an example

Code:
# MACD MTF
# Modified by tomsk
# 11.9.2019

declare lower;

input Agg1 = AggregationPeriod.THREE_MIN;
input Agg2 = AggregationPeriod.FIVE_MIN;
input Agg3 = AggregationPeriod.FIFTEEN_MIN;
input Agg4 = AggregationPeriod.Thirty_MIN;

input fastLength = 12;
input slowLength = 26;
input MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;

DefineGlobalColor("UpTrend", Color.GREEN);
DefineGlobalColor("DownTrend", Color.MAGENTA);

# Aggregation 1

def Value1 = MovingAverage(averageType, close(period = Agg1), fastLength) -
             MovingAverage(averageType, close(period = Agg1), slowLength);
def Avg1 = MovingAverage(averageType, Value1, MACDLength);
def Diff1 = Value1 – Avg1;
def MACDAgg1 = if Diff1 > 0 then 1 else if Diff1 < 0 then -1 else 0;
plot MACD1 = if IsNaN(close) then Double.NaN else 1;
MACD1.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD1.SetLineWeight(2);
MACD1.AssignValueColor(if MACDAgg1 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

# Aggregation 2

def Value2 = MovingAverage(averageType, close(period = Agg2), fastLength) -
             MovingAverage(averageType, close(period = Agg2), slowLength);
def Avg2 = MovingAverage(averageType, Value2, MACDLength);
def Diff2 = Value2 – Avg2;
def MACDAgg2 = if Diff2 > 0 then 1 else if Diff2 < 0 then -1 else 0;
plot MACD2 = if IsNaN(close) then Double.NaN else 2;
MACD2.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD2.SetLineWeight(2);
MACD2.AssignValueColor(if MACDAgg2 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

# Aggregation 3

def Value3 = MovingAverage(averageType, close(period = Agg3), fastLength) -
             MovingAverage(averageType,close(period = Agg3), slowLength);
def Avg3 = MovingAverage(averageType, Value3, MACDLength);
def Diff3 = Value3 – Avg3;
def MACDAgg3 = if Diff3 > 0 then 1 else if Diff3 < 0 then -1 else 0;
plot MACD3 = if IsNaN(close) then Double.NaN else 3;
MACD3.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD3.SetLineWeight(2);
MACD3.AssignValueColor(if MACDAgg3 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

# Aggregation 4

def Value4 = MovingAverage(averageType, close(period = Agg4), fastLength) -
             MovingAverage(averageType,close(period = Agg4), slowLength);
def Avg4 = MovingAverage(averageType, Value4, MACDLength);
def Diff4 = Value4 – Avg4;
def MACDAgg4 = if Diff4 > 0 then 1 else if Diff4 < 0 then -1 else 0;
plot MACD4 = if IsNaN(close) then Double.NaN else 4;
MACD4.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD4.SetLineWeight(2);
MACD4.AssignValueColor(if MACDAgg4 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));
 
I

imnobody

Member
@mike101 I have fixed up your code so that the MTF plots properly. Also I have resequenced and cleaned up the code for variables not used as well as utilized more meaningful variable names for any future work you may wish to do. Load this study on a 1 minute chart of AAPL as an example

Code:
# MACD MTF
# Modified by tomsk
# 11.9.2019

declare lower;

input Agg1 = AggregationPeriod.THREE_MIN;
input Agg2 = AggregationPeriod.FIVE_MIN;
input Agg3 = AggregationPeriod.FIFTEEN_MIN;
input Agg4 = AggregationPeriod.Thirty_MIN;

input fastLength = 12;
input slowLength = 26;
input MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;

DefineGlobalColor("UpTrend", Color.GREEN);
DefineGlobalColor("DownTrend", Color.MAGENTA);

# Aggregation 1

def Value1 = MovingAverage(averageType, close(period = Agg1), fastLength) -
             MovingAverage(averageType, close(period = Agg1), slowLength);
def Avg1 = MovingAverage(averageType, Value1, MACDLength);
def Diff1 = Value1 – Avg1;
def MACDAgg1 = if Diff1 > 0 then 1 else if Diff1 < 0 then -1 else 0;
plot MACD1 = if IsNaN(close) then Double.NaN else 1;
MACD1.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD1.SetLineWeight(2);
MACD1.AssignValueColor(if MACDAgg1 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

# Aggregation 2

def Value2 = MovingAverage(averageType, close(period = Agg2), fastLength) -
             MovingAverage(averageType, close(period = Agg2), slowLength);
def Avg2 = MovingAverage(averageType, Value2, MACDLength);
def Diff2 = Value2 – Avg2;
def MACDAgg2 = if Diff2 > 0 then 1 else if Diff2 < 0 then -1 else 0;
plot MACD2 = if IsNaN(close) then Double.NaN else 2;
MACD2.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD2.SetLineWeight(2);
MACD2.AssignValueColor(if MACDAgg2 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

# Aggregation 3

def Value3 = MovingAverage(averageType, close(period = Agg3), fastLength) -
             MovingAverage(averageType,close(period = Agg3), slowLength);
def Avg3 = MovingAverage(averageType, Value3, MACDLength);
def Diff3 = Value3 – Avg3;
def MACDAgg3 = if Diff3 > 0 then 1 else if Diff3 < 0 then -1 else 0;
plot MACD3 = if IsNaN(close) then Double.NaN else 3;
MACD3.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD3.SetLineWeight(2);
MACD3.AssignValueColor(if MACDAgg3 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));

# Aggregation 4

def Value4 = MovingAverage(averageType, close(period = Agg4), fastLength) -
             MovingAverage(averageType,close(period = Agg4), slowLength);
def Avg4 = MovingAverage(averageType, Value4, MACDLength);
def Diff4 = Value4 – Avg4;
def MACDAgg4 = if Diff4 > 0 then 1 else if Diff4 < 0 then -1 else 0;
plot MACD4 = if IsNaN(close) then Double.NaN else 4;
MACD4.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD4.SetLineWeight(2);
MACD4.AssignValueColor(if MACDAgg4 == 1 then GlobalColor("UpTrend") else GlobalColor("DownTrend"));
i don't understand this. so my timeframe is below the indicator's mtf? That doesn't make any sense to me for practicality or am I using it wrong? because I'd like to use a 30 min chart with macd agg periods something like 1min,5min,10min,15min but it doesn't work that way.I'd have to use periods larger than 30 min. Is there a way to change this if so?
 
T

tomsk

Well-known member
VIP
Warehouse
You can only reference higher aggregation, but not a lower aggregation than the chart you’re on. In other words, the aggregation on the chart is the primary while the other aggregation you're referencing are termed "secondary". You can only go up, not down.
 
I

imnobody

Member
You can only reference higher aggregation, but not a lower aggregation than the chart you’re on. In other words, the aggregation on the chart is the primary while the other aggregation you're referencing are termed "secondary". You can only go up, not down.
seriously? that's horrible. this isn't aimed towards you whatsoever but that is seriously so stupid... how does that make any sense when using a mtf?! you take signals when the lower frames align. why would i take a 30 min trade because the weekly and daily n 4hr align. you'd take a trade because lower frames are foreshadowing the move to your higher frame. wow i'm actually dumbfounded
 
T

tomsk

Well-known member
VIP
Warehouse
That is a TOS quirk, if you don't like it, then complain to TOS directly
 
I

imnobody

Member
That is a TOS quirk, if you don't like it, then complain to TOS directly
i should,ive sent them stuff before and i really dont think they take any of it into consideration but perhaps if we spam them enough they might. how would i put it though? because i dont understand the coding behind why it doesnt work. would saying something like the aggregation period only goes from higher to lower when making multi time frame indicators and should be able to go lower to higher?
 
T

tomsk

Well-known member
VIP
Warehouse
@HighBredCloud @netarchitech In light of your earlier note, as a proof of concept here is version 2 of the MACD MTF that incorporates the 4 colors of the standard TOS MACD depending on the following states.

Positive and Up
Positive and Down
Negative and Down
Negative and Up

Please note that this is not the standard way a typical MTF functions and is provided here as a proof of concept in case you are interested.

Code:
# MACD MTF
# Modified by tomsk
# 11.13.2019

# V11.09.2019 - tomsk - clean up mike101's code so that the MTF plots properly.
# V11.13.2019 - tomsk - added additional color coding similar to standard TOS MACD

declare lower;

input Agg1 = AggregationPeriod.THREE_MIN;
input Agg2 = AggregationPeriod.FIVE_MIN;
input Agg3 = AggregationPeriod.FIFTEEN_MIN;
input Agg4 = AggregationPeriod.Thirty_MIN;

input fastLength = 12;
input slowLength = 26;
input MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;

def PosUp = 1;
def PosDn = 2;
def NegDn = 3;
def NegUp = 4;

DefineGlobalColor("Positive and Up", Color.GREEN);
DefineGlobalColor("Positive and Down", Color.DARK_GREEN);
DefineGlobalColor("Negative and Down", Color.RED);
DefineGlobalColor("Negative and Up", Color.DARK_RED);

# Aggregation 1

def Value1 = MovingAverage(averageType, close(period = Agg1), fastLength) -
             MovingAverage(averageType, close(period = Agg1), slowLength);
def Avg1 = MovingAverage(averageType, Value1, MACDLength);
def Diff1 = Value1 – Avg1;
def MACDAgg1 = if Diff1 >= 0
               then if Diff1 > Diff1[1]
                    then PosUp
                    else PosDn
               else if Diff1 < Diff1[1]
                    then NegDn
                    else NegUp;
plot MACD1 = if IsNaN(close) then Double.NaN else 1;
MACD1.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD1.SetLineWeight(2);
MACD1.AssignValueColor(if MACDAgg1 == PosUp then GlobalColor("Positive and Up")
                       else if MACDAgg1 == PosDn then GlobalColor("Positive and Down")
                       else if MACDAgg1 == NegDn then GlobalColor("Negative and Down")
                       else GlobalColor("Negative and Up"));
# Aggregation 2

def Value2 = MovingAverage(averageType, close(period = Agg2), fastLength) -
             MovingAverage(averageType, close(period = Agg2), slowLength);
def Avg2 = MovingAverage(averageType, Value2, MACDLength);
def Diff2 = Value2 – Avg2;
def MACDAgg2 = if Diff2 >= 0
               then if Diff2 > Diff2[1]
                    then PosUp
                    else PosDn
               else if Diff2 < Diff2[1]
                    then NegDn
                    else NegUp;
plot MACD2 = if IsNaN(close) then Double.NaN else 2;
MACD2.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD2.SetLineWeight(2);
MACD2.AssignValueColor(if MACDAgg2 == PosUp then GlobalColor("Positive and Up")
                       else if MACDAgg2 == PosDn then GlobalColor("Positive and Down")
                       else if MACDAgg2 == NegDn then GlobalColor("Negative and Down")
                       else GlobalColor("Negative and Up"));
# Aggregation 3

def Value3 = MovingAverage(averageType, close(period = Agg3), fastLength) -
             MovingAverage(averageType,close(period = Agg3), slowLength);
def Avg3 = MovingAverage(averageType, Value3, MACDLength);
def Diff3 = Value3 – Avg3;
def MACDAgg3 = if Diff3 >= 0
               then if Diff3 > Diff3[1]
                    then PosUp
                    else PosDn
               else if Diff3 < Diff3[1]
                    then NegDn
                    else NegUp;
plot MACD3 = if IsNaN(close) then Double.NaN else 3;
MACD3.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD3.SetLineWeight(2);
MACD3.AssignValueColor(if MACDAgg3 == PosUp then GlobalColor("Positive and Up")
                       else if MACDAgg3 == PosDn then GlobalColor("Positive and Down")
                       else if MACDAgg3 == NegDn then GlobalColor("Negative and Down")
                       else GlobalColor("Negative and Up"));
# Aggregation 4

def Value4 = MovingAverage(averageType, close(period = Agg4), fastLength) -
             MovingAverage(averageType,close(period = Agg4), slowLength);
def Avg4 = MovingAverage(averageType, Value4, MACDLength);
def Diff4 = Value4 – Avg4;
def MACDAgg4 = if Diff4 >= 0
               then if Diff4 > Diff4[1]
                    then PosUp
                    else PosDn
               else if Diff4 < Diff4[1]
                    then NegDn
                    else NegUp;
plot MACD4 = if IsNaN(close) then Double.NaN else 4;
MACD4.SetPaintingStrategy(PaintingStrategy.POINTS);
MACD4.SetLineWeight(2);
MACD4.AssignValueColor(if MACDAgg4 == PosUp then GlobalColor("Positive and Up")
                       else if MACDAgg4 == PosDn then GlobalColor("Positive and Down")
                       else if MACDAgg4 == NegDn then GlobalColor("Negative and Down")
                       else GlobalColor("Negative and Up"));

# END CODE
 
netarchitech

netarchitech

Well-known member
VIP
Warehouse
@tomsk @HighBredCloud Sounds good @tomsk ...can we adapt it to the 3-in-1 project as we are not going for the MTF aspect? If so can we move the code over to the 3-in-1 project thread?
 
T

tomsk

Well-known member
VIP
Warehouse
@netarchitech @HighBredCloud It's all about code usability. So long as there is a use for code segments, feel free.
However let's do respect @BenTen methodology of maintaining some structure in this forum or else it may get cumbersome for him to keep track
Either way I have no qualms
 
netarchitech

netarchitech

Well-known member
VIP
Warehouse
@tomsk @HighBredCloud Sounds good...I definitely don't want to make more work for @BenTen What are your thoughts overall, @tomsk ?
 
T

tomsk

Well-known member
VIP
Warehouse
@netarchitech Let's switch to the proper indicator forum for further follow up

 
S

shizah

New member
@tomsk - your MTF MACD v1 is fantastic. Is it possible to make it an upper study?
 
T

tomsk

Well-known member
VIP
Warehouse
@shizah doing so would most likely clutter/overlay the candles, that is the reason why MTF studies typically are lower study based.
 
S

shizah

New member
@tomsk - That is true. I tried just simply moving as an upper study. Here a chart with a script that does do that. Not sure if this will help with this indicator and the CSA project you are working on.

 
T

tomsk

Well-known member
VIP
Warehouse
@shizah That link you posted sure looks like an earlier version of the MACC study done several years ago. ;)
 

Top