Skip to main content

Best Practices

Tips and patterns for reliable, efficient signal implementation.

1. Always Include Strategy Key​

Every signal needs strategy_key and position_side, and in practice also exchange and ticker matching the bot.

✅ Good​

{
"strategy_key": "your_strategy_key_here",
"exchange": "BINANCE",
"ticker": "BTCUSDT.P",
"position_side": "LONG",
"action": "BUY",
"leverage": 5
}

❌ Bad​

{
"position_side": "LONG",
"action": "BUY"
}
// Missing strategy_key - will be rejected

Store Strategy Keys Securely​

// ✅ Good: Environment variable
const STRATEGY_KEY = process.env.OPTALGO_STRATEGY_KEY;

// ❌ Bad: Hardcoded in public code
const STRATEGY_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";

2. Use Trade IDs for Position Management​

Trade IDs let one bot hold several trades at the same time. Most TradingView bots hold one trade at a time and do not need them. If you use them, send the same trade_id on the entry and on every exit for it, and keep it at 36 characters or fewer.

Opening with Trade ID​

{
"strategy_key": "your_key",
"exchange": "BINANCE",
"ticker": "BTCUSDT.P",
"position_side": "LONG",
"action": "BUY",
"leverage": 5,
"trade_id": "BTC_LONG_001",
"entry_price": 50000
}

Later, Close Specific Trade​

{
"strategy_key": "your_key",
"exchange": "BINANCE",
"ticker": "BTCUSDT.P",
"position_side": "CLOSE",
"trade_id": "BTC_LONG_001"
}

Trade ID Naming Conventions​

// ✅ Good: Descriptive IDs
trade_id: "BTC_LONG_20240115_001"
trade_id: "ETH_SHORT_SCALP"
trade_id: "SOL_SWING_TRADE"

// ⚠️ Avoid: Generic IDs (harder to track)
trade_id: "1"
trade_id: "trade"
trade_id: "abc"

3. Implement Safety Checks​

Send periodic validation signals to ensure position consistency between OptAlgo and external systems.

Enable Safety Checks​

{
"strategy_key": "your_key",
"exchange": "BINANCE",
"ticker": "BTCUSDT.P",
"position_side": "VALIDATE_ALERT",
"in_position": true,
"safety_check": true,
"safety_check_interval_minutes": 720
}

The interval is limited to 240-1440 minutes (default 1440). If no validation arrives for twice the interval while a trade is open, OptAlgo closes the trade.

  • Day Trading: 240-480 minutes (4-8 hours)
  • Swing Trading: 720-1440 minutes (12-24 hours)
  • Long-Term: 1440 minutes (24 hours)

TradingView Integration​

//@version=5
// Paste your bot's strategy key into this input in the script settings.
strategyKey = input.string("", "OptAlgo strategy key")

// Send a validation every 8 hours. Create the TradingView alert with the
// condition "Any alert() function call" and the OptAlgo webhook URL.
inPosition = strategy.position_size != 0
if barstate.isconfirmed and hour % 8 == 0 and minute == 0
alert('{"strategy_key":"' + strategyKey + '","exchange":"BINANCE","ticker":"' + syminfo.ticker + '","position_side":"VALIDATE_ALERT","in_position":' + str.tostring(inPosition) + ',"safety_check":true,"safety_check_interval_minutes":480}', alert.freq_once_per_bar_close)

TradingView placeholders such as {{ticker}} are not filled in inside alert() messages, so the script builds the JSON from syminfo.ticker and the key input.


4. Let OptAlgo Create Transaction IDs​

OptAlgo creates a transaction_id for every entry that has none, and uses it to group the trade's orders in the logs. You do not need to send one. If you do, use a fresh UUID per trade. Values like batch_001 fail the format check, and a static value does not protect against duplicate webhooks.


5. Proper Symbol Format​

Use correct symbol format to avoid errors.

✅ Correct​

Futures:

  • "BTCUSDT.P"
  • "ETHUSDT.P"
  • "SOLUSDT.P"

Spot:

  • "BTCUSDT"
  • "ETHUSDT"
  • "SOLUSDT"

❌ Wrong​

  • "BTCUSD.P" - Missing T
  • "BTC/USDT" - Wrong separator
  • "BTCUSDT.P" for spot - Incorrect suffix
  • "BTCUSDT" for futures - Missing .P

6. Validate Prices for Entry Signals​

Ensure proper price relationships before sending signals.

LONG Positions​

stop_loss_price < entry_price < take_profit_price
{
"position_side": "LONG",
"action": "BUY",
"entry_price": 50000,
"stop_loss_price": 48000, // ✅ Below entry
"take_profit_price": 55000 // ✅ Above entry
}

SHORT Positions​

take_profit_price < entry_price < stop_loss_price
{
"position_side": "SHORT",
"action": "SELL",
"entry_price": 50000,
"take_profit_price": 45000, // ✅ Below entry
"stop_loss_price": 52000 // ✅ Above entry
}

7. Use Reason Field for Debugging​

Include descriptive reasons to help with debugging and analysis.

// Entry signal
{
"strategy_key": "your_key",
"position_side": "LONG",
"action": "BUY",
"reason": "Golden cross on 4H timeframe"
}

// Close signal
{
"strategy_key": "your_key",
"position_side": "CLOSE",
"reason": "Stop loss hit - market downturn"
}

// Update signal
{
"strategy_key": "your_key",
"position_side": "MOVE_STOP_LOSS",
"stop_loss_price": 50000,
"reason": "Move to break even after 1:1 RR"
}

8. Always Use Stop Loss​

Protect your capital with stop loss orders.

✅ Good: Has Stop Loss​

{
"position_side": "LONG",
"entry_price": 50000,
"stop_loss_price": 48000,
"take_profit_price": 55000
}

⚠️ Risky: No Stop Loss​

{
"position_side": "LONG",
"entry_price": 50000,
"take_profit_price": 55000
}
// No protection if market moves against you

9. Start with Lower Leverage​

Use conservative leverage, especially when starting.

✅ Conservative​

{
"leverage": 3,
"margin_mode": "isolated"
}

⚠️ Higher Risk​

{
"leverage": 20,
"margin_mode": "cross"
}

10. Test with Paper Trading First​

Use paper trading to test strategies without risk.

Paper or live is a setting of the bot, not of the signal. Create the bot as a paper bot (auto and multi-symbol bots start on paper), run your alerts against it, and switch it to live in the app when you are satisfied. Do not send is_paper_strategy in your signals.

Paper bots have no exchange-side stop-loss or take-profit. Send a CLOSE when your stop or target is hit.


11. Scale Into and Out of Positions​

Use progressive entry and exit for better risk management.

Scale In​

// Entry 1: 33%
{
"tradable_ratio": 0.33,
"trade_id": "BTC_SCALE_1"
}

// Entry 2: 33%
{
"tradable_ratio": 0.33,
"trade_id": "BTC_SCALE_2"
}

// Entry 3: 34%
{
"tradable_ratio": 0.34,
"trade_id": "BTC_SCALE_3"
}

Scale Out​

// Exit 1: 33%
{
"position_side": "CLOSE_PARTIAL",
"close_ratio": 0.33,
"trade_id": "BTC_001"
}

// Exit 2: another 33% of the ORIGINAL size (close_ratio never refers to the remainder)
{
"position_side": "CLOSE_PARTIAL",
"close_ratio": 0.33,
"trade_id": "BTC_001"
}

// Exit 3: Remaining
{
"position_side": "CLOSE",
"trade_id": "BTC_001"
}

12. Move Stop Loss to Break Even​

After gaining profit, protect capital by moving stop to entry.

// Initial entry at 50000
{
"entry_price": 50000,
"stop_loss_price": 48000,
"trade_id": "BTC_001"
}

// Price reaches 52000 (1:1 RR) - move SL to break even.
// MOVE_STOP_LOSS replaces both orders: resend the take profit you want to keep.
{
"position_side": "MOVE_STOP_LOSS",
"stop_loss_price": 50000,
"take_profit_price": 56000,
"trade_id": "BTC_001",
"reason": "Move to break even after 1:1 RR"
}

Let winners run with trailing stops in strong trends.

{
"strategy_key": "your_key",
"position_side": "LONG",
"action": "BUY",
"entry_price": 50000,
"stop_loss_price": 48000,
"take_profit_price": 53000, // the trailing stop activates here
"is_trailing_stop_enabled": true,
"callback_rate": 1.0
}

14. One Bot per Symbol, or a Multi-Symbol Bot​

A single-symbol bot accepts signals for its own symbol only. Use one bot per trading pair, or a multi-symbol bot (Plus and Pro plans) to trade many coins with one key.

✅ Good​

// Strategy 1 for BTC
{
"strategy_key": "btc_strategy_key",
"ticker": "BTCUSDT.P"
}

// Strategy 2 for ETH
{
"strategy_key": "eth_strategy_key",
"ticker": "ETHUSDT.P"
}

❌ Bad​

// Using same strategy for different symbols
{
"strategy_key": "same_key",
"ticker": "BTCUSDT.P" // Today
}

{
"strategy_key": "same_key",
"ticker": "ETHUSDT.P" // Tomorrow - will cause mismatch error
}

15. Include PineScript Version​

When using TradingView, include PineScript version for better support.

{
"strategy_key": "your_strategy_key_here",
"exchange": "BINANCE",
"ticker": "{{ticker}}",
"position_side": "LONG",
"action": "BUY",
"leverage": 5,
"pinescript_code_version": "opt_v6"
}

{{strategy_key}} is not a TradingView placeholder: paste your bot's actual key into the alert message.


Common Patterns​

Pattern 1: Conservative Entry​

{
"strategy_key": "your_key",
"position_side": "LONG",
"action": "BUY",
"entry_price": 50000,
"stop_loss_price": 49000,
"take_profit_price": 52000,
"leverage": 3,
"margin_mode": "isolated",
"trade_id": "BTC_CONSERVATIVE"
}

Pattern 2: Aggressive Scalp​

{
"strategy_key": "your_key",
"position_side": "LONG",
"action": "BUY",
"entry_order_type": "MARKET",
"stop_loss_price": 49800,
"take_profit_price": 50200,
"leverage": 20,
"trade_id": "BTC_SCALP"
}

Pattern 3: Swing with Trailing Stop​

{
"strategy_key": "your_key",
"position_side": "LONG",
"action": "BUY",
"entry_price": 50000,
"stop_loss_price": 47000,
"take_profit_price": 53000,
"is_trailing_stop_enabled": true,
"callback_rate": 2.0,
"leverage": 5,
"trade_id": "BTC_SWING"
}

Next Steps​