The SwingArm
Menu trading academy
THE IMPLEMENTATION OF SWINGARMS
The code included below is made available free of charge to anyone interested in learning to read price action using the swingarms. The code below includes the single time frame and as well as the multi timeframe code. While looking at charts and interpreting a single time frame is easy, the multi timeframe understanding does require some study. Please take the time to learn and paper trade as long as you may need. Do not risk any funds you can not afford to lose. The code below is written in ThinkScript and it is done specifically for ThinkOrSwim.
Trading Links
WARNING!
The use of the Single and Multi Timeframe SwingArm provides a visual interpretation of what is going on with the instrument that is being analyzed be it the Standard And Poors 500 index, Russell 2000, Nasdaq, Gold, Forex or Crypto Currencies, etc.
Its use provides any trader a competitive advantage by having a forward-looking indicator to project into the future potential points of support/resistance allowing for an opportunity ahead of the event occurring.
This does not mean that there is no risk. In the markets, anything can happen and I mean anything. So, plan ahead and stick to your plan.
blackFLAG SwingArm Code. Update 5/24/2020
# Original Code From: TD Ameritrade IP Company, Inc. (c) 2009-2020
# Original StudyName: ATRTrailingStop
# Type: Study
# blackFLAG FTS SwingArms
# StudyName: blackFLAG_Futures_SwingArm_ATRTrail
# My preferred setting is 28 / 5 FOR ALL TIMEFRAMES
# Edited by Jose Azcarate
# blackFLAG Futures Trading – FOR EDUCATIONAL PURPOSES ONLY
# TWITTER: @blackflagfuture
# UPDATED: 5/16/2020
# NOTE: WHEN IMPORTING STUDY, MAKE SURE YOU UPDATE THE LOOK AND FEEL TO MATCH MY CHARTS WITHIN THE STUDY SETTINGS.
#———————————–
input trailType = {default modified, unmodified};
input ATRPeriod = 28;
input ATRFactor = 5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;
input fib1Level = 61.8;
input fib2Level = 78.6;
input fib3Level = 88.6;
Assert(ATRFactor > 0, “‘atr factor’ must be positive: ” + ATRFactor);
def HiLo = Min(high – low, 1.5 * Average(high – low, ATRPeriod));
def HRef = if low <= high[1]
then high – close[1]
else (high – close[1]) – 0.5 * (low – high[1]);
def LRef = if high >= low[1]
then close[1] – low
else (close[1] – low) – 0.5 * (low[1] – high);
def trueRange;
switch (trailType) {
case modified:
trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);
def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
if (!IsNaN(loss)) {
switch (firstTrade) {
case long:
state = state.long;
trail = close – loss;
case short:
state = state.short;
trail = close + loss;
}
} else {
state = state.init;
trail = Double.NaN;
}
case long:
if (close > trail[1]) {
state = state.long;
trail = Max(trail[1], close – loss);
} else {
state = state.short;
trail = close + loss;
}
case short:
if (close < trail[1]) {
state = state.short;
trail = Min(trail[1], close + loss);
} else {
state = state.long;
trail = close – loss;
}
}
def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);
def ex = if BuySignal then high else if SellSignal then low else if state == state.long then Max(ex[1], high) else if state == state.short then Min(ex[1], low) else ex[1];
plot TrailingStop = trail;
TrailingStop.SetPaintingStrategy(PaintingStrategy.POINTS);
TrailingStop.DefineColor(“Long”, Color.GREEN);
TrailingStop.DefineColor(“Short”, Color.RED);
TrailingStop.AssignValueColor(if state == state.long
then TrailingStop.Color(“Long”)
else TrailingStop.Color(“Short”));
plot Extremum = ex;
Extremum.SetPaintingStrategy(PaintingStrategy.POINTS);
Extremum.DefineColor(“HH”, Color.GREEN);
Extremum.DefineColor(“LL”, Color.RED);
Extremum.AssignValueColor(if state == state.long
then Extremum.Color(“HH”)
else Extremum.Color(“LL”));
Extremum.Hide();
def f1 = ex + (trail – ex) * fib1Level / 100;
def f2 = ex + (trail – ex) * fib2Level / 100;
def f3 = ex + (trail – ex) * fib3Level / 100;
def l100 = trail + 0;
plot Fib1 = f1;
Fib1.SetPaintingStrategy(PaintingStrategy.POINTS);
Fib1.SetDefaultColor(Color.BLACK);
Fib1.Hide();
plot Fib2 = f2;
Fib2.SetPaintingStrategy(PaintingStrategy.POINTS);
Fib2.SetDefaultColor(Color.BLACK);
Fib2.Hide();
plot Fib3 = f3;
Fib3.SetPaintingStrategy(PaintingStrategy.POINTS);
Fib3.SetDefaultColor(Color.BLACK);
Fib3.Hide();
AddCloud(f1, f2, Color.LIGHT_GREEN, Color.LIGHT_RED, no);
AddCloud(f2, f3, Color.GREEN, Color.RED, no);
AddCloud(f3, l100, Color.DARK_GREEN, Color.DARK_RED, no);
def l1 = state[1] == state.long and close crosses below f1[1];
def l2 = state[1] == state.long and close crosses below f2[1];
def l3 = state[1] == state.long and close crosses below f3[1];
def s1 = state[1] == state.short and close crosses above f1[1];
def s2 = state[1] == state.short and close crosses above f2[1];
def s3 = state[1] == state.short and close crosses above f3[1];
def atr = Average(TrueRange(high, close, low), 14);
plot LS1 = if l1 then low – atr else Double.NaN;
plot LS2 = if l2 then low – 1.5 * atr else Double.NaN;
plot LS3 = if l3 then low – 2 * atr else Double.NaN;
plot SS1 = if s1 then high + atr else Double.NaN;
plot SS2 = if s2 then high + 1.5 * atr else Double.NaN;
plot SS3 = if s3 then high + 2 * atr else Double.NaN;
LS1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LS1.SetDefaultColor(Color.GREEN);
LS1.SetLineWeight(1);
LS1.Hide();
LS2.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LS2.SetDefaultColor(Color.GREEN);
LS2.SetLineWeight(1);
LS2.Hide();
LS3.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LS3.SetDefaultColor(Color.GREEN);
LS3.SetLineWeight(1);
LS3.Hide();
SS1.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SS1.SetDefaultColor(Color.RED);
SS1.SetLineWeight(1);
SS1.Hide();
SS2.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SS2.SetDefaultColor(Color.RED);
SS2.SetLineWeight(1);
SS2.Hide();
SS3.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SS3.SetDefaultColor(Color.RED);
SS3.SetLineWeight(1);
SS3.Hide();
Alert(l1, “Price crossed below Fib1 level in long trend”, Alert.BAR, Sound.Bell);
Alert(l2, “Price crossed below Fib2 level in long trend”, Alert.BAR, Sound.Bell);
Alert(l3, “Price crossed below Fib3 level in long trend”, Alert.BAR, Sound.Bell);
Alert(s1, “Price crossed above Fib1 level in short trend”, Alert.BAR, Sound.Bell);
Alert(s2, “Price crossed above Fib2 level in short trend”, Alert.BAR, Sound.Bell);
Alert(s3, “Price crossed above Fib3 level in short trend”, Alert.BAR, Sound.Bell);
# *******************************************************
# DAY TRADING SETTINGS USING 1 AND 5 MINUTE CHARTS
AddLabel(yes,” DAY TRADING STRATEGY : “,color.WHITE);
AddLabel(yes, if ohlc4 > TrailingStop then “* IF * 5 Min. SWINGARM Is BULLISH – Buy 1 Min. Zone 4” else “* IF * 5 MIN. SWINGARM – Is BEARISH – Sell 1 Min Zone 4”, if ohlc4 > TrailingStop then Color.GREEN else Color.Red);
# SWING TRADING SETTINGS USING 4 HOUR CHART ( needs work below )
# AddLabel(yes,” SWING TRADING STRATEGY : “,color.WHITE);
# AddLabel(yes, if ohlc4 > TrailingStop then “* IF * 4 Hour SWINGARM Is BULLISH – Wait For Entry Confirmation” else “* IF * 4 Hour SWINGARM – Is BEARISH – Wait For Entry Confirmation”, if ohlc4 > TrailingStop then Color.GREEN else Color.RED);
MULTI TIMEFRAME SWINGARM CODE
# Original Code From: TD Ameritrade IP Company, Inc. (c) 2009-2020
# Original StudyName: ATRTrailingStop
# Type: Study
# CODE NOT FOR SALE.
# blackFLAG Futures Trading System Indicator – SwingArms
# StudyName: blackFLAG_Futures_SwingArm_ATRTrail
# Edited by: Jose Azcarate
# EMAIL: joseazcarate@msn.com
# blackFLAG Futures Trading – FOR EDUCATIONAL PURPOSES ONLY
# TWITTER: @blackflagfuture
# UPDATED: 9/9/2020
# MODIFIED: 6/6/2020
# MTF SwingArm Break – Labels * MTF Labels
# Credit: @diazlaz
# MODIFIED: 6/11/20 – allows defining the period you want the swingarm to draw – This is an add-on to be used with the main SwingArm Script, all alters have been removed.
# Credit: @xzeryn
# MODIFIED: 9/7/2020
# Added zone 2, 3 and 3 labels. Ability to turn on/off buy / sell labels and swingarm bucket zones. Added price line.
# Credit: @vsr_2803
#———————————–
input aggregationPeriod = AggregationPeriod.MIN;
input ShowBuyBubbles = YES;
input ShowSellBubbles = YES;
input trailType = {default modified, unmodified};
input ATRPeriod = 28;
input ATRFactor = 5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;
input fib1Level = 61.8;
input fib2Level = 78.6;
input fib3Level = 88.6;
Assert(ATRFactor > 0, “‘atr factor’ must be positive: ” + ATRFactor);
def high = high(period = aggregationPeriod);
def low = low(period = aggregationPeriod);
def close = close(period = aggregationPeriod);
def HiLo = Min(high – low, 1.5 * Average(high – low, ATRPeriod));
def HRef = if low <= high[1]
then high – close[1]
else (high – close[1]) – 0.5 * (low – high[1]);
def LRef = if high >= low[1]
then close[1] – low
else (close[1] – low) – 0.5 * (low[1] – high);
def trueRange;
switch (trailType) {
case modified:
trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);
def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
if (!IsNaN(loss)) {
switch (firstTrade) {
case long:
state = state.long;
trail = close – loss;
case short:
state = state.short;
trail = close + loss;
}
} else {
state = state.init;
trail = Double.NaN;
}
case long:
if (close > trail[1]) {
state = state.long;
trail = Max(trail[1], close – loss);
} else {
state = state.short;
trail = close + loss;
}
case short:
if (close < trail[1]) {
state = state.short;
trail = Min(trail[1], close + loss);
} else {
state = state.long;
trail = close – loss;
}
}
def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);
def ex = if BuySignal then high else if SellSignal then low else if state == state.long then Max(ex[1], high) else if state == state.short then Min(ex[1], low) else ex[1];
plot TrailingStop = trail;
TrailingStop.SetPaintingStrategy(PaintingStrategy.LINE);
TrailingStop.DefineColor(“Long”, Color.GREEN);
TrailingStop.DefineColor(“Short”, Color.RED);
TrailingStop.SetLineWeight(5);
TrailingStop.AssignValueColor(if state == state.long
then TrailingStop.Color(“Long”)
else TrailingStop.Color(“Short”));
#TrailingStop.hide();
plot Extremum = ex;
Extremum.SetPaintingStrategy(PaintingStrategy.POINTS);
Extremum.DefineColor(“HH”, Color.GREEN);
Extremum.DefineColor(“LL”, Color.RED);
Extremum.AssignValueColor(if state == state.long
then Extremum.Color(“HH”)
else Extremum.Color(“LL”));
Extremum.Hide();
def sDir = if state == state.long then 100 else -100;
def f1 = ex + (trail – ex) * fib1Level / 100;
def f2 = ex + (trail – ex) * fib2Level / 100;
def f3 = ex + (trail – ex) * fib3Level / 100;
def l100 = trail + 0;
plot Fib1 = f1;
Fib1.SetPaintingStrategy(PaintingStrategy.LINE);
Fib1.SetDefaultColor(Color.White);
plot Fib2 = f2;
Fib2.SetPaintingStrategy(PaintingStrategy.Line);
Fib2.SetDefaultColor(Color.White);
plot Fib3 = f3;
Fib3.SetPaintingStrategy(PaintingStrategy.Line);
Fib3.SetDefaultColor(Color.White);
Fib3.SetLineWeight(2);
AddCloud(f1, f2, Color.LIGHT_GREEN, Color.LIGHT_RED, no);
AddCloud(f2, f3, Color.GREEN, Color.RED, no);
AddCloud(f3, l100, Color.DARK_GREEN, Color.DARK_RED, no);
def l1 = state[1] == state.long and close crosses below f1[1];
def l2 = state[1] == state.long and close crosses below f2[1];
def l3 = state[1] == state.long and close crosses below f3[1];
def s1 = state[1] == state.short and close crosses above f1[1];
def s2 = state[1] == state.short and close crosses above f2[1];
def s3 = state[1] == state.short and close crosses above f3[1];
def atr = Average(TrueRange(high, close, low), 14);
plot LS1 = if l1 then low – atr else Double.NaN;
plot LS2 = if l2 then low – 1.5 * atr else Double.NaN;
plot LS3 = if l3 then low – 2 * atr else Double.NaN;
plot SS1 = if s1 then high + atr else Double.NaN;
plot SS2 = if s2 then high + 1.5 * atr else Double.NaN;
plot SS3 = if s3 then high + 2 * atr else Double.NaN;
LS1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LS1.SetDefaultColor(Color.GREEN);
LS1.SetLineWeight(1);
LS1.Hide();
LS2.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LS2.SetDefaultColor(Color.GREEN);
LS2.SetLineWeight(1);
LS2.Hide();
LS3.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LS3.SetDefaultColor(Color.GREEN);
LS3.SetLineWeight(1);
LS3.Hide();
SS1.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SS1.SetDefaultColor(Color.RED);
SS1.SetLineWeight(1);
SS1.Hide();
SS2.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SS2.SetDefaultColor(Color.RED);
SS2.SetLineWeight(1);
SS2.Hide();
SS3.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SS3.SetDefaultColor(Color.RED);
SS3.SetLineWeight(1);
SS3.Hide();
AddChartBubble(sDir == 100 and sDir != sDir[1] , f3 ,
if aggregationPeriod == 60000 then “1 Min BUY Bucket”
else if aggregationPeriod == 120000 then “2 Min BUY Bucket”
else if aggregationPeriod == 180000 then “3 Min BUY Bucket”
else if aggregationPeriod == 240000 then “4 Min BUY Bucket”
else if aggregationPeriod == 300000 then “5 Min BUY Bucket”
else if aggregationPeriod == 600000 then “10 Min BUY Bucket”
else if aggregationPeriod == 900000 then “15 Min BUY Bucket”
else if aggregationPeriod == 1800000 then “30 Min BUY Bucket”
else if aggregationPeriod == 3600000 then “1 Hour BUY Bucket”
else if aggregationPeriod == 7200000 then “2 Hour BUY Bucket”
else if aggregationPeriod == 14400000 then “4 Hours BUY Bucket”
else if aggregationPeriod == 86400000 then “1 Day BUY Bucket”
else if aggregationPeriod == 604800000 then “1 Week BUY Bucket”
else if aggregationPeriod == 2592000000 then “1 Month BUY Bucket”
else (aggregationPeriod / 1000 / 60) + “Min BUY Bucket”, Color.GREEN,no);
AddChartBubble(sDir == -100 and sDir != sDir[1] , f3 ,
if aggregationPeriod == 60000 then “1 Min SELL Bucket”
else if aggregationPeriod == 120000 then “2 Min SELL Bucket”
else if aggregationPeriod == 180000 then “3 Min SELL Bucket”
else if aggregationPeriod == 240000 then “4 Min SELL Bucket”
else if aggregationPeriod == 300000 then “5 Min SELL Bucket”
else if aggregationPeriod == 600000 then “10 Min SELL Bucket”
else if aggregationPeriod == 900000 then “15 Min SELL Bucket”
else if aggregationPeriod == 1800000 then “30 Min SELL Bucket”
else if aggregationPeriod == 3600000 then “1 Hour SELL Bucket”
else if aggregationPeriod == 7200000 then “2 Hour SELL Bucket”
else if aggregationPeriod == 14400000 then “4 Hours SELL Bucket”
else if aggregationPeriod == 86400000 then “1 Day SELL Bucket”
else if aggregationPeriod == 604800000 then “1 Week SELL Bucket”
else if aggregationPeriod == 2592000000 then “1 Month SELL Bucket”
else (aggregationPeriod / 1000 / 60) + “Min SELL Bucket”, Color.RED, yes);
addchartBubble(isnan(close[1]) and !isnan(close[2]),f3[3],
if aggregationPeriod == 60000 then “1 Min”
else if aggregationPeriod == 120000 then “2 Min”
else if aggregationPeriod == 180000 then “3 Min”
else if aggregationPeriod == 240000 then “4 Min”
else if aggregationPeriod == 300000 then “5 Min”
else if aggregationPeriod == 600000 then “10 Min”
else if aggregationPeriod == 900000 then “15 Min”
else if aggregationPeriod == 1800000 then “30 Min”
else if aggregationPeriod == 3600000 then “1 Hour”
else if aggregationPeriod == 7200000 then “2 Hour”
else if aggregationPeriod == 14400000 then “4 Hours”
else if aggregationPeriod == 86400000 then “1 Day”
else if aggregationPeriod == 604800000 then “1 Week”
else if aggregationPeriod == 2592000000 then “1 Month”
else (aggregationPeriod / 1000 / 60) + “Min”
, if sDir == 100 then COLOR.YELLOW else COLOR.YELLOW);
def lowerPeriod = GetAggregationPeriod();
def numberOfLowerInHigher = aggregationPeriod/lowerPeriod;
def counter = counter[1] +1;
def pSwitch = if counter % numberOfLowerInHigher == 0 then if pSwitch[1] == 1 then 0 else 1 else pSwitch[1];
def per1 = if pSwitch == 0 then 1 else double.nan;
def per2 = if pSwitch == 1 then 1 else double.nan;
def per3 = if counter % numberOfLowerInHigher == RoundDown(numberOfLowerInHigher/2,0) then barnumber() else double.nan;
def hb = if per3 then high else double.nan;
def lb = if per3 then low else double.nan;
#input LineWeight =1;
#Plot hb1 = hb;
#Plot lb1 = lb;
#AddChart(high = hb, low = lb, open = double.nan, close = double.nan, type = ChartType.bar, growcolor = color.white);
Plot BUY3 = if LS2 and !SellSignal then lb else Double.NaN;
BUY3.Hide();
Plot BUY4 = if LS3 and !SellSignal then lb else Double.NaN;
BUY4.Hide();
#AddChartBubble(ShowBuyBubbles,BUY3,”Long Z3″, Color.LIGHT_GREEN,01);
AddChartBubble(ShowBuyBubbles,BUY4,”BUY SLINGSHOT”, Color.YELLOW,01);
Plot SELL3 = if SS2 and !buySignal then hb else Double.NaN;
SELL3.Hide();
Plot SELL4 = if SS3 and !buySignal then hb else Double.NaN;
SELL4.Hide();
#AddChartBubble(ShowSellBubbles,SELL3,”Short Z3″, Color.LIGHT_RED,01);
AddChartBubble(ShowSellBubbles,SELL4,”SELL SLINGSHOT”, Color.YELLOW,01);
# Display Label
#AddLabel(yes,”: “,color.YELLOW);
#AddLabel(yes, if ohlc4 > TrailingStop then ” ALTERNATE BUY SETUP ACTIVE ” else ” ALTERNATE SELL SETUP ACTIVE “, if ohlc4 > TrailingStop then Color.YELLOW else Color.YELLOW);
#AddLabel(yes, Concat(“Alt SA Period: “, if aggregationperiod < 3600000 then aggregationperiod/60000 + “m” else if aggregationperiod < 86400000 then aggregationperiod/3600000 + “h” else if aggregationperiod < 604800000 then aggregationperiod/86400000 + “D” else if aggregationperiod < 2592000000 then aggregationperiod/604800000 + “Wk” else if aggregationperiod < 31536000000 then aggregationperiod/2592000000 + “Mo” else aggregationperiod/31536000000 + “Yr”),color.WHITE);