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.
Recommended Intervals
- 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"
}
13. Use Trailing Stops for Trends
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
- Troubleshooting - Common errors and solutions
- Examples - Complete working examples
- Signal Flow - Understand signal processing