Get started
documentation

Shifu docs

Everything you need to send a TradingView alert to your broker account: the click-by-click setup, the full alert format with copy-ready examples, exactly what each broker route does with an order, and how to fix an alert that was refused.

Last updated: July 24, 2026

What Shifu is(link to this section)

A router. Your alert goes in, the matching order goes out to your own broker account.

Shifu sits between TradingView and the brokerage accounts you connect. Your chart fires an alert, Shifu reads it, and sends the matching order to whichever of your accounts you pointed that bot at. That is the entire job.

Two things drive every order: the alert your script sends, and the configuration on the bot and on each account you routed it to. Nothing else is added along the way.

  • A bot is one TradingView alert wired to one or more of your accounts. It has its own private link.
  • An account is a brokerage or prop-firm account you connect, or a paper account for rehearsal.
  • Routing is the on/off switch plus the size rule that connects a bot to an account.

Quick start(link to this section)

Connect an account, create a bot, paste the link into TradingView, go live.

  1. 1 · Connect an account

    Dashboard → Accounts → Connect account. Paper needs no broker login and is the right place to start — fake money, realistic fills. For a real account, pick Tradovate or Rithmic — the ProjectX card is there but disabled until that route is built. Trading on NinjaTrader? Pick NinjaTrader and Shifu asks the one question that resolves it: if you sign in with a Tradovate or NinjaTrader username and password, Shifu connects over Tradovate; if your firm gave you a system name like “Rithmic 01”, it connects over Rithmic.

  2. 2 · Create a bot

    Dashboard → Bots → New bot. Set a name, a Default ticker (for example MES1!), a Default size, and How to size each trade. On save you get your private link and a key that is shown exactly once — copy it then. If you lose it, rotate the secret from the bot’s Setup tab and re-paste the new link in TradingView.

  3. 3 · Point the bot at your accounts

    Open the bot → Account routing. Turn on each account this bot should trade. Per account you choose Contracts (this account always trades that many, whatever the alert says) or × alert (multiply whatever size the alert sends). If the bot sizes from the alert, only the multiplier applies.

  4. 4 · Wire it into TradingView

    On the bot’s Setup tab, copy your link and copy a ready-made message. In TradingView press Alt+A, set the condition to your strategy or indicator with “Any alert() function call”, open the Notifications tab, tick Webhook URL and paste the link, then paste the message into the Message box. If your script builds its own alert text, leave the Message box empty. Click Create.

  5. 5 · Fire a test, then go live

    Send a test signal from the bot’s Setup tab and watch it land under Alerts. When you are ready for real orders, turn on Live routing on the account. Live routing is one of two switches — real orders also require Shifu’s platform-wide live trading to be open. Until then an armed account stays ready and paper keeps working exactly as it will live.

Setting up the TradingView alert(link to this section)

One alert, with two things pasted into it: your link and your message. Here is every click.

You do this once per bot. The alert lives on your chart in TradingView; Shifu only ever sees the message that alert sends. Which message you paste comes down to one question — who writes it, your script or you? Pick your path first, then follow the dialog steps below.

  1. Path A · Your script writes the message

    The easiest case. If your strategy or indicator already builds its own alert text (most coded strategies, and anything already formatted for PickMyTrade or TradersPost), leave the Message box empty and set the condition to “Any alert() function call”. Shifu reads whatever your script sends. Nothing to paste into the Message box at all.

  2. Path B · You can’t edit the script

    A protected or premium strategy you cannot add code to. Set the alert’s condition to that strategy with the trigger “Order fills only”, and paste the order-fills message from the bot’s Setup tab. TradingView reports each order the strategy fills, and the position fields in that message let Shifu tell entries, exits, and reversals apart on its own — full exit handling, zero code.

  3. Path C · It’s an indicator

    An indicator or built-in signal — an RSI level, a moving-average cross, and the like. Make one alert per side you trade (long, short, exit), each on that condition and set to “Once Per Bar Close”, and paste that side’s message from the Setup tab. Indicator alerts cannot use strategy placeholders, so the per-side messages carry no {{strategy.*}} text.

  1. 1 · Open the alert dialog

    On your chart, press Alt+A (or click the clock icon at the top right). TradingView’s “Create Alert” panel opens.

  2. 2 · Set the condition

    In the Condition area, pick your strategy or indicator, then the trigger for your path above — “Any alert() function call” for Path A, “Order fills only” for Path B, or your indicator’s own condition for Path C.

  3. 3 · Turn on the webhook

    Open the Notifications tab and tick “Webhook URL”. Paste your link from the bot’s Setup tab into that field. Paste the whole link, including the key on the end — that key is what proves the alert came from you.

  4. 4 · Paste the message

    Scroll to the “Message” box. Clear TradingView’s default text and paste the message you copied in Step 2. On Path A, where your script writes the message itself, leave this box empty instead.

  5. 5 · Create

    Click Create. From now on the alert fires whenever your condition is true, and each fire sends exactly one message to Shifu.

Alert format(link to this section)

The Message box holds one JSON object. Three fields are required; everything else is opt-in.

The simplest alert that does something is an action, a symbol, and a key that makes this alert unique. Everything below that is you asking for more precision.

Long entry
{
  "action": "buy",
  "symbol": "MES1!",
  "quantity": 1,
  "idempotency_key": "{{timenow}}-long"
}
actionrequiredbuy · sell · close · exit · reverse
What to do. buy and sell open or add in that direction. close and exit both flatten your position in that symbol. reverse asks to flip an open position to the other side — see the broker notes below, because reverse is not accepted on every account type.
symbolrequireda futures contract, e.g. MES1!
Which contract to trade. Use the TradingView continuous form (MES1!, MNQ1!) and Shifu resolves it to the current front month for you, so you never have to edit an alert at rollover. A dated contract works too, but stops working once it expires.
idempotency_keyrequiredletters, numbers, and . _ : -
A unique id for this alert. Two alerts arriving with the same key within a minute are treated as one, so a retriggered or double-delivered alert cannot fill twice. Use {{timenow}}-long on an indicator alert, or {{time}}-{{strategy.order.id}} on a strategy alert.
quantityoptionalwhole number, 1 to 10,000
How many contracts the alert is asking for. Used when the bot is set to size from the alert. Left out, the bot’s Default size is used instead. Each account can still scale or override this on the Account routing tab.
order_typeoptionalmarket · limit · stop · stop_limit
How the entry goes to market. Defaults to market when you leave it out.
limit_priceoptionala price
The limit price for the entry. Required whenever order_type is limit or stop_limit — the alert is refused without it.
stop_priceoptionala price
The trigger price for the entry. Required whenever order_type is stop or stop_limit — the alert is refused without it.
priceoptionala price
Where your chart was when the alert fired. It is a reference, never a constraint: a market order still fills at market. Shifu uses it to price paper fills honestly and to place bracket levels exactly where your chart computed them, so include it whenever your script can.
take_profitoptionala price
An absolute price for a resting take-profit. When present, Shifu places it at the broker as a limit order the moment the entry fills. Leave the field out entirely if you do not want this leg.
stop_lossoptionala price
An absolute price for a resting stop. Placed at the broker alongside the take-profit; a fill on either one cancels the other. Leave the field out entirely if you do not want this leg.
trail_distanceoptionala distance in the symbol’s price units
How far behind the best price the stop should follow. Including this field turns the stop leg into a trailing stop at the broker instead of a fixed one. Your initial stop still sits exactly where stop_loss put it, so your opening risk always matches your plan.
trail_triggeroptionala distance in the symbol’s price units
How far price must move in your favour before the trail starts following. Leave it out to trail from entry. Honoured on Rithmic accounts; see the broker table for what happens elsewhere.
market_positionoptionallong · flat · short
Where TradingView says the strategy stands after this order. This is what makes a strategy you cannot edit fully automatable: a bare buy or sell that leaves the strategy flat is read as a close.
prev_market_positionoptionallong · flat · short
Where the strategy stood before this order. Paired with market_position, a straight flip from long to short (or back) is read as a reverse rather than a plain entry.
metaoptionalany JSON object
Anything else you want kept with the alert — a setup name, a tag, a note. Shifu stores it with the record so you can see it later. It never changes routing.
Bracket: entry plus a resting take-profit and stop
{
  "action": "buy",
  "symbol": "MES1!",
  "quantity": 1,
  "price": 5000.25,
  "take_profit": 5010.25,
  "stop_loss": 4995.25,
  "idempotency_key": "{{timenow}}-long"
}
Trailing stop: fixed initial risk, then it follows
{
  "action": "sell",
  "symbol": "MNQ1!",
  "quantity": 1,
  "price": 18250.00,
  "stop_loss": 18270.00,
  "trail_distance": 8,
  "trail_trigger": 12,
  "idempotency_key": "{{timenow}}-short"
}
Limit entry at the alert bar’s close
{
  "action": "buy",
  "symbol": "MES1!",
  "quantity": 1,
  "order_type": "limit",
  "limit_price": "{{close}}",
  "idempotency_key": "{{timenow}}-long"
}
Stop entry above the market (breakout)
{
  "action": "buy",
  "symbol": "MES1!",
  "quantity": 1,
  "order_type": "stop",
  "stop_price": 5012.50,
  "idempotency_key": "{{timenow}}-long"
}
Short entry with a resting bracket
{
  "action": "sell",
  "symbol": "MNQ1!",
  "quantity": 2,
  "price": 18250.00,
  "take_profit": 18230.00,
  "stop_loss": 18262.00,
  "idempotency_key": "{{timenow}}-short"
}
Exit whatever is open
{
  "action": "exit",
  "symbol": "MES1!",
  "idempotency_key": "{{timenow}}-exit"
}
A strategy you cannot edit, using TradingView’s order fills
{
  "action": "{{strategy.order.action}}",
  "symbol": "{{ticker}}",
  "quantity": "{{strategy.order.contracts}}",
  "market_position": "{{strategy.market_position}}",
  "prev_market_position": "{{strategy.prev_market_position}}",
  "idempotency_key": "{{time}}-{{strategy.order.id}}"
}

Supported contracts: ES, MES, NQ, MNQ, RTY, M2K, YM, MYM, CL, MCL, NG, GC, MGC, SI, ZB, ZN, ZF, ZT, 6E, 6J, 6B, and the CME crypto futures BTC, MBT, ETH, MET, SOL, MSL, XRP and MXP. Anything outside that list is refused with a symbol-unknown message rather than guessed at.

Order types(link to this section)

Market, limit, stop, and stop-limit entries. Brackets and trailing stops rest at the broker.

  • Market — the default. Sent as soon as the alert lands; fills at whatever the market gives you.
  • Limit — set order_type to limit and give a limit_price. Rests until filled or cancelled.
  • Stop — set order_type to stop and give a stop_price. Triggers into a market order.
  • Stop-limit — set order_type to stop_limit and give both a stop_price and a limit_price.
  • Bracket — include take_profit and/or stop_loss on an entry. Both legs rest at the broker as one group the instant the entry fills, and a fill on one cancels the other.
  • Trailing stop — add trail_distance to a bracket. The stop leg becomes a trailing stop at the broker instead of a fixed one.

When a bracket is resting at the broker, the exit is already sitting there and does not depend on another alert arriving. That is the point of using one: your exit does not wait on TradingView.

Brokers, and what differs(link to this section)

Tradovate / NinjaTrader accounts are live. Rithmic is built and ready for its first live account. ProjectX is not switched on yet. Paper is built in. The differences between the routes are small but they are real.

PaperTradovateRithmicProjectX
Market · limit · stop · stop-limitYesYesYesNot yet
Bracket resting at the brokerSimulatedYesYesNot yet
Trailing stop legSimulatedYesYesNot yet
trail_trigger honouredYesYesYesNot yet
close / exit alertsYesYesYesNot yet
reverse alertsYesNoNoNot yet
Flattens before a new entryYesYesNoNot yet
Balance & positions shown in ShifuSimulatedYesNoNot yet

Every verdict here is the behavior in the shipped routing code. Tradovate / NinjaTrader accounts are live today — real orders route over that rail. Rithmic is built and conformance-passed, and ready for its first live account — no live order has routed over it yet. ProjectX is not switched on — nothing routes there, and the connect card says so instead of letting you wire an account that cannot trade. A Yes in a column that is not live yet means the code is there and conformance-tested, not that orders have run through it in production. And on Rithmic, your balance and open positions are not read back into Shifu — you watch them in your trading platform. The other routes show them for you.

  • Paper — the rehearsal route, no broker login and nothing real at stake. Every order type, resting bracket, trailing stop and the running balance are simulated from your own alerts, so you can run the whole loop end to end before a live account is ever involved. The numbers are Shifu’s simulation, not a market feed.
  • Tradovate — the fullest route. Market, limit, stop and stop-limit entries, a resting take-profit and stop bracket, and a native trailing stop with an arm-after trigger all work, and your balance and open positions sync back into Shifu. You sign in on Tradovate’s own site and approve Shifu, so your password is never typed into Shifu. Pick Simulated or Live — most prop-firm accounts, funded ones included, run on Simulated.
  • Rithmic — built and conformance-passed, waiting on its first live account: no live order has routed over it yet. What the adapter does when one arrives: every order type, resting brackets, and a trailing stop with the same arm-after trigger (trail_trigger) Tradovate honours, following last trade rather than bid/ask. Two things to know: Rithmic does not flatten a prior position before a new entry, so send an explicit exit alert first if you need to be flat; and your balance and open positions live in your trading platform, not yet inside Shifu. You sign in with your Rithmic username, the system name your firm gave you (for example “Rithmic 01”), and your account number, each spelled exactly as your firm shows it — spaces and capitals included.
  • ProjectX — the prop-firm route behind platforms like TopstepX and Bulenox. It is not built yet: the card in the account picker reads “coming” and is disabled, so there is nothing to connect or configure today. Firms that only sign in over ProjectX — TopstepX and Bulenox — are not supported today. Use paper or another route until then.
  • NinjaTrader — not a separate route. NinjaTrader is both a platform and a brokerage (NinjaTrader Clearing, LLC also trades as Tradovate), so a NinjaTrader account reaches Shifu over either Tradovate or Rithmic, and the account picker asks the one question that settles it: a Tradovate or NinjaTrader username and password means Tradovate; a system name like “Rithmic 01” means Rithmic.

How size is decided(link to this section)

The bot decides the base size. Each account can scale it or fix it outright.

  1. 1 · The bot picks a base size

    How to size each trade on the bot’s Settings tab decides where the number comes from. From the TradingView alert uses the alert’s quantity, and falls back to Default size when the alert leaves it out. Fixed contracts always uses Default size and ignores what the alert sent.

  2. 2 · Each account applies its own rule

    On Account routing, an account is either on × alert, which multiplies the base size (1× is the same size, 2× is double), or on Contracts, which trades that exact number no matter what the alert says. Contracts is only offered when the bot is not sizing from the alert — a fixed count would contradict an alert-driven bot.

  3. 3 · The result is rounded to whole contracts

    The scaled number is rounded, and never goes below one contract. Nothing is ever rounded down to zero and silently dropped.

The same alert can land as a different size on each account. Here one buy for 2 contracts is routed to three accounts, each with its own rule on the routing tab — the message never changes:

One alert, three accounts
{
  "action": "buy",
  "symbol": "MES1!",
  "quantity": 2,
  "idempotency_key": "{{timenow}}-long"
}
AccountIts routing ruleContracts sent
Account A× 1 — same size2
Account B× 24
Account C× 36

The size difference is the per-account rule, not the alert. Multipliers apply when the bot sizes from the alert. To trade a flat count on one account no matter what the alert says, switch the bot to a fixed size and set that account to Contracts instead of a multiplier.

What Shifu will and won’t do(link to this section)

A router forwards. Knowing exactly where that line sits keeps your expectations honest.

Shifu’s job is narrow on purpose: take the alert your script sends and place the matching order on the accounts you chose. It is not a strategy, not a risk manager, and not a second opinion. Everything it does is either delivering your order or a mechanical safeguard on the delivery itself.

Shifu will:

  • Forward every valid alert to each account you routed the bot to, in the order your script fires them.
  • Place market, limit, stop and stop-limit orders, and rest a take-profit and stop bracket at the broker when your alert carries one.
  • Read the position your alert reports and turn a bare buy or sell into the right action, so a strategy you cannot edit still closes and flips correctly.
  • Resolve a continuous symbol (MES1!, MNQ1!) to the current front month, so you never edit an alert at rollover.
  • Write down every alert and every refusal on your Alerts page, with the exact message that caused it.

Shifu won’t:

  • Decide whether a trade is a good idea, hold a signal back because it disagrees, or add a trade you did not send.
  • Watch a daily loss limit, a drawdown, or your trading hours, or flatten you to protect an account — your prop firm enforces its own rules, and Shifu never pretends to be that layer.
  • Give trading, sizing, or timing advice.
  • Chase a fill. If a hand-off to the broker does not land, it is skipped and recorded — never quietly sent again seconds later at a worse price.
  • Send an alert to any account you did not route, or copy anyone else’s trades. Multi-account means your own alert going to your own accounts, nothing more.

What can stop an alert(link to this section)

A short, closed list. None of it is an opinion about your trade.

Shifu forwards what you send. The only things that stop an alert are mechanical: it is a duplicate, it is malformed, you paused the bot, you exceeded a limit you set, or routing it would leave your own accounts contradicting each other. Shifu never withholds an order because it disagrees with the trade.

  • Duplicates — two alerts carrying the same idempotency_key within a minute count as one. The second gets the same result as the first instead of a second fill.
  • Runaway protection — a bot ignores alerts beyond its per-minute cap so a stuck script cannot machine-gun your account. On by default; you control the cap in the bot’s settings.
  • Paused bot — a paused bot drops alerts and records that they arrived, so you can see the alert was fired and the bot was off.
  • Malformed messages — an alert that is not JSON, that is missing a required field, or that names a contract Shifu does not support is refused with the reason.
  • Oversized messages — an alert message larger than 8 KB is refused.
  • Conflicting accounts — when one bot routes to two or more accounts, Shifu will not send an order that would leave you long in one and short in another. The alert is refused and each account records why, so you can resync rather than discover a hedge later.

Every refusal is written to your Alerts page with the reason and the message that caused it, so nothing fails silently.

Troubleshooting(link to this section)

The six things that actually go wrong, what they look like, and the fix.

Invalid signature

you see
TradingView reports a failed webhook and your Alerts page shows an invalid-signature rejection.

do this
The link is missing its key. Re-copy the full link from the bot’s Setup tab — everything, including the part after the question mark — and paste it into the alert again. If you rotated the bot’s secret, the old link stops working and every alert using it must be re-pasted.

Unresolved placeholders

you see
The rejection quotes your own message back at you with the braces still in it, like {{strategy.order.action}}.

do this
TradingView only fills strategy placeholders on strategy alerts using order-fill events. On an indicator alert the text is sent literally. Use the per-side indicator message from the Setup tab, or point the alert at a strategy and choose its order fills.

Not JSON, or unknown format

you see
The rejection says the message is not JSON, or that the format is not recognised.

do this
Something other than a message object is in the Message box — usually TradingView’s default alert text. Clear the box and paste one of the ready-made messages from the Setup tab. If your script builds its own alert text, leave the box completely empty.

Symbol unknown

you see
The alert is refused naming the contract you sent.

do this
Use the continuous form (MES1!, MNQ1!) so rollover is handled for you. A dated contract stops resolving once it expires, and contracts outside the supported list are refused rather than guessed at.

Bot paused

you see
Alerts show up on the Alerts page as rejected, with a note that the bot is paused.

do this
Flip Status back on in the bot’s Settings tab. This one is good news: it means your link, key and message are all correct and the alert arrived exactly as intended.

Rate limited

you see
Some alerts fill and later ones in the same minute are refused for exceeding the bot’s limit.

do this
Runaway protection caught a burst. First check the TradingView alert is set to “Once Per Bar Close”; a tick-triggered alert is the usual cause. If the burst was a script bug, fix the script — that is what the cap is for. If your strategy genuinely fires that often, raise the cap in the bot’s settings.

A field failed validation

you see
The refusal names one field — a price, the quantity, the symbol — as missing, mistyped, or out of range.

do this
Shifu understood the shape but one value was wrong: a limit or stop entry with no price, a quantity above 10,000, or a take-profit or stop sent as 0. Fix just the named field in the Message box and fire again — everything else was fine.

Message too large

you see
The alert is refused for size before Shifu even reads it.

do this
The Message box is over the 8 KB ceiling. Trim it to what Shifu needs — action, symbol, quantity and any bracket prices — and drop comments, debug text, and fields Shifu does not read.

Something here wrong or missing? Email support@paradoxalgo.com. Shifu is operated by Paradox Algo, LLC.