Indicator · Pine Script v5 · On the chart

Bollinger and ATR Bands

by SynergOps· code credited to AlexanderTeaH (Original Author)

This indicator plots standard Bollinger Bands alongside scaled Average True Range (ATR) bands directly on the price chart.

View on GitHub

GitHub stars7on the repository
Pine versionv5runs as is
Lines of code230
Settings18inputs
LicenceMPL-2.0
Last update1 year ago4 Aug 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

230 lines of Pine Script v5 from Bollinger Bands with ATR - Indicator/bb-atr.pine, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.

bb-atr.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AlexanderTeaH (Original Author)
// © TheTrdFloor (modifications and documantation)
// © Salih Emin (personal modifications)
//
// In many strategies, it's quite common to use a scaled ATR to help define a stop-loss, and it's not uncommon to use it for take-profit targets
// as well.  While there are quite a few indicators that plot ATR bands already on TV, we could not find one that actually performed the exact 
// way that we wanted.  They all had at least one of the following gaps:
//   * The ATR offset was not configurable (usually hard-coded to be based off the high or low, while we generally prefer to use close)
//   * It would only print a single band (either the upper or lower), which would require the same indicator to be added twice
//   * The ATR scaling factor was either not configurable or only stepped in whole numbers (often time fractional factors like 1.5 yield better results)
//
// Also, when looking at some of the behaviors of the ATR bands, you can see that when price first levels out, you can draw a "consolidation zone" from
// the first peak of the upper ATR band to the first valley of the lower ATR band and look for price to break and close outside of that zone.  When that
// happens, price will usually make a notable move in that direction.
//
// While we have made some updates and enhancements to this indicator, and have every intention of continuing to do so as we find worthy opportunities
// for enhancement, credit is still due to the origianl author:  AlexanderTeaH
//
//@version=5
indicator('Bollinger and ATR Bands', overlay=true) // These had to be taken out as they're not compatible with plotting a table...   , timeframe="", timeframe_gaps=false

// Bollinger bands
length = input.int(20, minval=1)
src = input(close, title="Source")
mult = input.float(2.0, minval=0.001, maxval=50, title="StdDev")
basis = ta.sma(src, length)
dev = mult * ta.stdev(src, length)
upper = basis + dev
lower = basis - dev
offset = input.int(0, "Offset", minval = -500, maxval = 500)
plot(basis, "Basis", color=#FF6D00, offset = offset)
p1 = plot(upper, "Upper", color=#000000, offset = offset)
p2 = plot(lower, "Lower", color=#000000, offset = offset)
fill(p1, p2, title = "Background", color=color.rgb(33, 150, 243, 95))

// ATR Inputs
atrPeriod = input.int(title='ATR Period', defval=14, minval=1, group="ATR Bands Standard Settings", tooltip="This setting is used in the raw ATR value calculation.  Lower values will be more reactive to recent price movement, while higher values will better indicate loger-term trend.\n\n" +
                 "Most often this is set at either 14 or 21.\nDefault: 14")

// While it seemed like a nice idea at the time, having separately-configurable upper and lower bands just doesn't really seem that useful as 90% of the time the settings for both are the same.
// Therefore, We're going to simplify the config to make these settings unified for both bands, as it would otherwise just add even more confusion with the addition of take-profit bands as well...
//
// atrMultiplierUpper = input.float(title='ATR Upper Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Upper Band Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands.  " +
//                     "This will usually be between 1 and 3.")
// srcUpper = input.source(title='ATR Upper Offset Source', defval=close, group="ATR Upper Band Settings", tooltip="This setting determines the offset point for ATR bands.  " +
//                     "For this band, 'high' and 'close' (default) are generally the most appropriate values.")
//
atrMultiplier = input.float(title='ATR Band Scale Factor', defval=1.5, step=0.1, minval=0.01, group="ATR Bands Standard Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands.  " +
                     "This will usually be between 1 and 3.\n\nDefault: 2.5")
// On second thought, I'm going to nix this setting and force it to be the "close" source.  Having the ability to offset based on the wicks was a nice idea, but doesn't really seem to have any notable practical application.
atrSourceRef = "close"
//atrSourceRef = input.string(title='ATR Upper Offset Source', defval="close", options=["close","wicks"], group="ATR Bands Standard Settings", tooltip="This setting determines the offset point for ATR bands.  " +
//                     "The default value 'close' should be your go-to, but 'wicks' might provide a bit more breathing room in securities that tend to have large wicks.")
//
// See above - these are deprecated and no longer used...
//
// atrMultiplierLower = input.float(title='ATR Lower Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Lower Band Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands.  " +
//                     "This will usually be between 1 and 3.")
// srcLower = input.source(title='ATR Lower Offset Source', defval=close, group="ATR Lower Band Settings", tooltip="This setting determines the offset point for ATR bands.  " +
//                     "For this band, 'low' and 'close' (default) are generally the most appropriate values.")
//
//
// Take-Profit band settings
showTPBands = input.bool(title="Show opposite bands for take-profit zones", defval=false, tooltip="If enalbled, the existing ATR bands will be treated as 'stop-loss' bands, and 'take-profit' bands will be plotted " +
                     "to depict potential take-profit targets that are scaled based on the 'stop-loss' band and an additional reward/risk scaling factor (see below).\n\nDefault: Unchecked", group="Take-Profit Settings")
tpScaleFactor = input.float(title="Take-Profit Scale Factor", defval=1.5, minval=1, step=0.1, tooltip="This is a secondary scaling factor used based on the 'stop-loss' ATR bands to calculate and plot a potential take-profit target.\n\n" + 
                     "The easiest way to think of this is as a desired reward/risk ratio, where the primary ATR Bands represent the risk/stop-loss.\n\nDefault: 1.5")
//
//
// As an added bonus, give the option to plot a table containing exact figures for all of the bands...
// Functional settings
showTable = input.bool(title="Show Table for Stops and Targets", defval=false, group="Table Settings", tooltip="If enabled, a table will be placed on-chart showing exact values for both stop bands, as well as optional take-profit bands/targets.\n\n" +
                     "Note: Take-profit values are based on the 'Take-Profit Scale Factor' setting above.\n\nDefault: Unchecked")
allowTableRepainting = input.bool(title="Allow Table Repainting", defval=false, group="Table Settings", tooltip="If enabled, table data will show real-time values, which will inherently repaint.  This may be desirable for people preparing to enter prior " +
                     "to candle close, but should be used with extreme caution.\n\nDefault: Unchecked")
showTPinTable = input.bool(title="Include additional rows/columns to display take-profit values.", defval=false, group="Table Settings", tooltip="If enabled, additional table rows/columns will be drawn and populated with take-profit band/target values.\n\n" +
                     "Note: Take-profit values are based on the 'Take-Profit Scale Factor' setting above.\n\nDefault: Unchecked")
//
// Display settings
alignTableVertically = input.bool(title="Align Table Vertically", defval=true, group="Table Settings", tooltip="If enabled, the table will be re-aligned to display vertically (headers to the left) instead of horizontally (headers on top).\n\nDefault: Checked")
tablePosition = input.string(title="Table Location", defval="Bottom Right", options=["Top Right","Top Left","Top Center","Middle Right","Middle Left","Middle Center","Bottom Right","Bottom Left","Bottom Center"], group="Table Settings", 
                     tooltip='This setting controls the position on the chart where the table will be located.\n\nDefault: Bottom Right')
tableColor = input.color(title="Table Color: ", defval=color.rgb(0, 175, 200, 20), group="Table Settings", inline="A")
tableTextHeaderColor = input.color(title="Table Header Color: ", defval=color.rgb(255, 255, 0, 0), group="Table Settings", tooltip="These settings determine the colors used for the table cell borders/outlines, and the text inside the table cells used as data headers.", inline="A")
tableTextColor = input.color(title="Table Text Color: ", defval=color.rgb(255, 255, 255, 0), group="Table Settings", tooltip="This setting determines the color used for the text inside the table cells.", inline="B")
// tableTooltipColor = input.color(title="Table Tooltip Color: ", defval=color.rgb(255, 75, 255, 0), group="Table Display Settings", tooltip="This setting determines the color used for any cell tooltips.") // Not used
tableLongBGColor = input.color(title="Table Background Color - Long: ", defval=color.rgb(0, 255, 0, 90), group="Table Settings", inline="C")
tableShortBGColor = input.color(title="Short: ", defval=color.rgb(255, 0, 0, 80), group="Table Settings", tooltip="These settings determine the background fill colors used for long/short position info.", inline="C")


// Functions
//
// Function to convert the input "source" to a proper "source"
getBandOffsetSource(srcIn, isUpperBand) =>
    // Initialize the return to our fail-safe 'close', which is also the default input, then update thru the switch statement
    ret = close
    switch srcIn
        "close" => ret := close
        "wicks" => ret := isUpperBand ? high : low
        => ret := close
    ret
//
// Function to convert table position input to a an appropriate argument
getTablePosition(posIn) =>
    posOut = position.bottom_right
    switch (posIn)
        "Top Right" => posOut := position.top_right
        "Top Left" => posOut := position.top_left
        "Top Center" => posOut := position.top_center
        "Middle Right" => posOut := position.middle_right
        "Middle Left" => posOut := position.middle_left
        "Middle Center" => posOut := position.middle_center
        "Bottom Right" => posOut := position.bottom_right
        "Bottom Left" => posOut := position.bottom_left
        "Bottom Center" => posOut := position.bottom_center
        => posOut := position.bottom_right
    posOut
    
// ATR
atr = ta.atr(atrPeriod)
scaledATR = atr * atrMultiplier
upperATRBand = getBandOffsetSource(atrSourceRef, true) + scaledATR
lowerATRBand = getBandOffsetSource(atrSourceRef, false) - scaledATR
//
// Since we can calcualte ATR bands based on either close or wicks, we need to be sure to normalize the true distance
// from the close to the "stop band" before we can then apply our take-profit scaler and calculate the TP bands...
scaledTPLong = close + ((close - lowerATRBand) * tpScaleFactor)
scaledTPShort = close - ((upperATRBand - close) * tpScaleFactor)

// OG ATR Band Plotting
plot(upperATRBand, title="Upper ATR Band", color=color.rgb(0, 255, 0, 50), linewidth=2, style = plot.style_stepline)
plot(lowerATRBand, title="Lower ATR Band", color=color.rgb(255, 0, 0, 50), linewidth=2, style = plot.style_stepline)

// TP band plots
plot(showTPBands ? scaledTPLong : na, title="Upper Take-Profit Band", color=color.rgb(255, 255, 255, 80), linewidth=1, style = plot.style_stepline)
plot(showTPBands ? scaledTPShort : na, title="Lower Take-Profit Band", color=color.rgb(255, 255, 0, 80), linewidth=1, style = plot.style_stepline)

// ATR and TP table...
if (showTable)
    // It's nice that TV will automagically shrink/reposition table cells to not have gaps if a specific row/column are missing,
    // so we can define the table to the max number of rows/columns possible for this indicator in any configuration and let TV handle the "shrinking".
    var atrTable = table.new(position=getTablePosition(tablePosition), columns=8, rows=8)
    //
    // Set the base table styles...
    table.set_border_width(atrTable, 1)
    table.set_frame_width(atrTable, 1)
    table.set_border_color(atrTable, tableColor)
    table.set_frame_color(atrTable, tableColor)
    //
    // Since we're giving the option to display the table with 2 different formats (horizontal vs vertical), we need to build out both variations and
    // incorporate a method to switch from one to the other based on the 'alignTableVertically' user input setting.  While we probably COULD do
    // conditional logic inside the 'table.cell' functions, it will be far more intuitive to "read" if we simply break it into an 'if-else' clause.
    // 
    // While this WILL result in a pretty notable duplication of code, it's acceptable in this case as we have a finite number of options (2).
    //
    // Vertical orientation
    if (alignTableVertically)
        // Define the Title/Header cells
        table.cell(atrTable, 0, 0, text="Long ATR Stop", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor, tooltip="Test")
        table.cell(atrTable, 0, 1, text="Long ATR Stop Dist", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor)
        if (showTPinTable)
            table.cell(atrTable, 0, 2, text="Long ATR TP", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 0, 3, text="Long ATR TP Dist", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor)
        table.cell(atrTable, 0, 4, text="Short ATR Stop", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
        table.cell(atrTable, 0, 5, text="Short ATR Stop Dist", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
        if (showTPinTable)
            table.cell(atrTable, 0, 6, text="Short ATR TP", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 0, 7, text="Short ATR TP Dist", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
        //
        // Now for table values for each header...
        // Start with Long position...
        table.cell(atrTable, 1, 0, text=str.tostring(allowTableRepainting ? lowerATRBand : lowerATRBand[1], format.mintick), text_color=tableTextColor, bgcolor=tableLongBGColor, tooltip="Test")
        table.cell(atrTable, 1, 1, text=str.tostring(math.round_to_mintick(allowTableRepainting ? close - lowerATRBand : close[1] - lowerATRBand[1])), text_color=tableTextColor, bgcolor=tableLongBGColor)
        if (showTPinTable)
            table.cell(atrTable, 1, 2, text=str.tostring(allowTableRepainting ? scaledTPLong : scaledTPLong[1], format.mintick), text_color=tableTextColor, bgcolor=tableLongBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 1, 3, text=str.tostring(math.round_to_mintick(allowTableRepainting ? scaledATR * tpScaleFactor : scaledATR[1] * tpScaleFactor)), text_color=tableTextColor, bgcolor=tableLongBGColor)
        // Now the Short position...
        table.cell(atrTable, 1, 4, text=str.tostring(allowTableRepainting ? upperATRBand : upperATRBand[1], format.mintick), text_color=tableTextColor, bgcolor=tableShortBGColor, tooltip="Test 2")
        table.cell(atrTable, 1, 5, text=str.tostring(math.round_to_mintick(allowTableRepainting ? upperATRBand - close : upperATRBand[1] - close[1])), text_color=tableTextColor, bgcolor=tableShortBGColor)
        if (showTPinTable)
            table.cell(atrTable, 1, 6, text=str.tostring(allowTableRepainting ? scaledTPShort : scaledTPShort[1], format.mintick), text_color=tableTextColor, bgcolor=tableShortBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 1, 7, text=str.tostring(math.round_to_mintick(allowTableRepainting ? scaledATR * tpScaleFactor : scaledATR[1] * tpScaleFactor)), text_color=tableTextColor, bgcolor=tableShortBGColor)
        
        
        
    //
    // Horizontal orientation
    else
        // Define the Title/Header cells
        table.cell(atrTable, 0, 0, text="Long ATR Stop", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor, tooltip="Test")
        table.cell(atrTable, 1, 0, text="Long ATR Stop Dist", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor)
        if (showTPinTable)
            table.cell(atrTable, 2, 0, text="Long ATR TP", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 3, 0, text="Long ATR TP Dist", text_color=tableTextHeaderColor, bgcolor=tableLongBGColor)
        table.cell(atrTable, 4, 0, text="Short ATR Stop", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
        table.cell(atrTable, 5, 0, text="Short ATR Stop Dist", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
        if (showTPinTable)
            table.cell(atrTable, 6, 0, text="Short ATR TP", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 7, 0, text="Short ATR TP Dist", text_color=tableTextHeaderColor, bgcolor=tableShortBGColor)
        //
        // Now for table values for each header...
        // Start with Long position...
        table.cell(atrTable, 0, 1, text=str.tostring(allowTableRepainting ? lowerATRBand : lowerATRBand[1], format.mintick), text_color=tableTextColor, bgcolor=tableLongBGColor, tooltip="Test")
        table.cell(atrTable, 1, 1, text=str.tostring(math.round_to_mintick(allowTableRepainting ? close - lowerATRBand : close[1] - lowerATRBand[1])), text_color=tableTextColor, bgcolor=tableLongBGColor)
        if (showTPinTable)
            table.cell(atrTable, 2, 1, text=str.tostring(allowTableRepainting ? scaledTPLong : scaledTPLong[1], format.mintick), text_color=tableTextColor, bgcolor=tableLongBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 3, 1, text=str.tostring(math.round_to_mintick(allowTableRepainting ? scaledATR * tpScaleFactor : scaledATR[1] * tpScaleFactor)), text_color=tableTextColor, bgcolor=tableLongBGColor)
        // Now the Short position...
        table.cell(atrTable, 4, 1, text=str.tostring(allowTableRepainting ? upperATRBand : upperATRBand[1], format.mintick), text_color=tableTextColor, bgcolor=tableShortBGColor, tooltip="Test 2")
        table.cell(atrTable, 5, 1, text=str.tostring(math.round_to_mintick(allowTableRepainting ? upperATRBand - close : upperATRBand[1] - close[1])), text_color=tableTextColor, bgcolor=tableShortBGColor)
        if (showTPinTable)
            table.cell(atrTable, 6, 1, text=str.tostring(allowTableRepainting ? scaledTPShort : scaledTPShort[1], format.mintick), text_color=tableTextColor, bgcolor=tableShortBGColor)
            // If the TP scale factor is exactly 1, we can nix the TP distance columns as it will be exactly the same as the stop distance.
            if (tpScaleFactor != 1)
                table.cell(atrTable, 7, 1, text=str.tostring(math.round_to_mintick(allowTableRepainting ? scaledATR * tpScaleFactor : scaledATR[1] * tpScaleFactor)), text_color=tableTextColor, bgcolor=tableShortBGColor)

Overview

Bollinger and ATR Bands is designed to assist traders in identifying price consolidation zones, potential breakout levels, dynamic stops, and take-profit targets. Users can customize Bollinger length and standard deviation multipliers, ATR calculation periods, and ATR scaling factors. An optional take-profit band visualization can be enabled. Additionally, an optional customizable dashboard table can be displayed on the chart to summarize current calculated stop-loss and take-profit target price levels for both long and short positions.

Details

Published by

SynergOps on GitHub

Code credit

AlexanderTeaH (Original Author), as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

Moving averages, Volatility & bands, Support & resistance, Screeners & dashboards

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
lengthint20length
Sourcesourceclosesrc
StdDevfloat2.0mult
Offsetint0offset
ATR Periodint14atrPeriod
ATR Band Scale Factorfloat1.5atrMultiplier
Show opposite bands for take-profit zonesboolfalseshowTPBands
Take-Profit Scale Factorfloat1.5tpScaleFactor
Show Table for Stops and TargetsboolfalseshowTable
Allow Table RepaintingboolfalseallowTableRepainting
Include additional rows/columns to display take-profit values.boolfalseshowTPinTable
Align Table VerticallybooltruealignTableVertically
Show all 18 settings
SettingTypeDefaultVariable
Table LocationstringBottom RighttablePosition
Table Color: colorcolor.rgb(0, 175, 200, 20)tableColor
Table Header Color: colorcolor.rgb(255, 255, 0, 0)tableTextHeaderColor
Table Text Color: colorcolor.rgb(255, 255, 255, 0)tableTextColor
Table Background Color - Long: colorcolor.rgb(0, 255, 0, 90)tableLongBGColor
Short: colorcolor.rgb(255, 0, 0, 80)tableShortBGColor
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

20 stars

This indicator calculates a base moving average (EMA, SMA, WMA, or HMA) and projects multiple symmetrical envelope bands around it directly on the price chart. Users can adjust the length, source, moving average type, and initial envelope multiplier. Additiona

Indicator v5 Moving averagesVolatility & bands
Updated 1 year ago · None stated GitHub repository of Multiple Moving Average Envelope

Bottom Level Finder

by chris-c-thomas
14 stars

Bottom Level Finder is a support identification indicator designed to locate correction and re-entry zones directly on the price chart. It calculates horizon-adaptive Fibonacci retracements, drawdown percentage levels, moving averages, and integrated VIX volat

Indicator v6 Support & resistanceMoving averages
Updated 6 months ago · MIT GitHub repository of Bottom Level Finder

This overlay indicator plots a Supertrend from an ATR length and factor, four exponential moving averages, and a selectable VWAP or TWAP taken from a chosen timeframe on the price chart. It also shows MACD and stochastic with adjustable lengths, smoothing, ver

Indicator v5 Oscillators & momentumMoving averages
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup: Vijay Thakare Option Buying Scalping Setup

Snag - VWAP

by dearvn
257 stars

This indicator plots a custom Anchored Volume-Weighted Average Price (VWAP) directly on the price chart along with optional standard deviation bands. Users can anchor the VWAP to standard time periods like sessions, weeks, or months, or to corporate events suc

Indicator v5 Moving averagesVolatility & bands Repaints
Updated 6 weeks ago · None stated GitHub repository of Snag - VWAP
218 stars

This indicator maps market structure and supply and demand zones on the price chart. It marks validated and optional unvalidated swing highs and lows using a pivot length and extra confirmation bars. Consolidation and impulse moves are measured against ATR to

Indicator v6 SMC / ICT / price actionSupport & resistance Repaints
Updated 3 months ago · None stated GitHub repository of Market Structure + Supply/Demand

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers