Getting Started with Custom Strategies
This guide walks you through creating your first custom trading strategy on TradeStaq.
Prerequisites
Before creating custom strategies, ensure you have:
- Basic JavaScript knowledge
- Understanding of trading concepts (entries, exits, stop loss, etc.)
- Any TradeStaq plan (custom strategies are available on all tiers)
- At least one connected exchange (paper trading recommended for testing)
Your First Strategy: Hello World
Let's start with a simple strategy that logs market information:
// Hello World Strategy
// Logs current market state on each spin
td.utils.log('Hello from my strategy!', {
symbol: td.market.symbol,
price: td.market.price,
rsi: td.indicators.rsi,
hasPosition: td.position.hasPosition,
spinCount: td.meta.spinCount
});
This strategy doesn't execute any trades - it simply logs information to help you understand the available data.
A Simple Trading Strategy
Now let's create a strategy that actually trades based on RSI:
// RSI Mean Reversion Strategy
// Buys when oversold, sells when overbought
const rsi = td.indicators.rsi;
const oversoldLevel = 30;
const overboughtLevel = 70;
if (!td.position.hasPosition) {
// No position - look for entry
if (rsi < oversoldLevel) {
td.trade.buy({
amountPercent: 100,
stopLoss: td.market.price * 0.98, // 2% stop loss
takeProfit: td.market.price * 1.04, // 4% take profit
reason: `RSI oversold at ${rsi.toFixed(2)}`
});
}
} else {
// In position - look for exit
if (rsi > overboughtLevel) {
td.trade.close(`RSI overbought at ${rsi.toFixed(2)}`);
}
}
Understanding the Code
Accessing Indicators
const rsi = td.indicators.rsi; // Current RSI value (14-period default)
The td.indicators object provides pre-calculated technical indicators. See the Indicators Guide for all available indicators.
Checking Position Status
if (!td.position.hasPosition) {
// No open position
}
The td.position object tells you about your current position:
hasPosition: Boolean - whether you have an open positionside: 'long', 'short', or 'none'pnl: Current unrealized profit/loss
Executing Trades
td.trade.buy({
amountPercent: 100, // Use 100% of available balance
stopLoss: price * 0.98, // Stop loss price
takeProfit: price * 1.04, // Take profit price
reason: 'Entry reason' // Logged for debugging
});
Available trade functions:
td.trade.buy()- Open a long positiontd.trade.sell()- Open a short positiontd.trade.close()- Close current position
Logging
td.utils.log('Message', { data: 'here' });
Logs are visible in the bot's activity panel. Use logging to debug your strategy.
Making Strategies Configurable
Hard-coding values like 30 for oversold is inflexible. Use td.config to make strategies configurable:
// Configurable RSI Strategy
const rsiPeriod = td.config.getNumber('RSI_PERIOD', 14);
const oversold = td.config.getNumber('RSI_OVERSOLD', 30);
const overbought = td.config.getNumber('RSI_OVERBOUGHT', 70);
const stopLossPercent = td.config.getNumber('STOP_LOSS_PCT', 2);
const takeProfitPercent = td.config.getNumber('TAKE_PROFIT_PCT', 4);
// Note: Standard RSI (14) is built-in. Custom periods require custom indicator configured in bot settings.
const rsi = rsiPeriod === 14 ? td.indicators.rsi : td.indicators.custom['rsi_' + rsiPeriod];
const price = td.market.price;
if (!td.position.hasPosition && rsi < oversold) {
td.trade.buy({
amountPercent: 100,
stopLoss: price * (1 - stopLossPercent / 100),
takeProfit: price * (1 + takeProfitPercent / 100),
reason: `RSI ${rsi.toFixed(2)} < ${oversold}`
});
} else if (td.position.hasPosition && rsi > overbought) {
td.trade.close(`RSI ${rsi.toFixed(2)} > ${overbought}`);
}
Users can then customize these parameters when creating a bot with your strategy.
Using State for Complex Logic
Sometimes you need to remember values between spins. Use td.state:
// Track consecutive losses
const consecutiveLosses = td.state.get('consecutiveLosses', 0);
const lastPnl = td.state.get('lastPnl', 0);
// Check if last trade was a loss
if (td.position.pnl < lastPnl && lastPnl !== 0) {
td.state.set('consecutiveLosses', consecutiveLosses + 1);
} else if (td.position.pnl > 0) {
td.state.set('consecutiveLosses', 0);
}
td.state.set('lastPnl', td.position.pnl);
// Pause trading after 3 consecutive losses
if (consecutiveLosses >= 3) {
td.utils.log('Pausing - 3 consecutive losses');
return; // Exit strategy early
}
// ... rest of trading logic
Testing Your Strategy
Before deploying with real money:
- Paper Trading: Always test on a paper exchange first
- Backtesting: Use the backtesting feature to test against historical data
- Small Positions: When going live, start with small position sizes
- Monitor Closely: Watch your bot's behavior for the first few days
Common Mistakes to Avoid
Trading on Every Spin
// BAD - Will trade too frequently
td.trade.buy({ amountPercent: 100 });
// GOOD - Only trade when conditions are met
if (rsi < 30 && !td.position.hasPosition) {
td.trade.buy({ amountPercent: 100 });
}
Ignoring Stop Losses
// BAD - No risk management
td.trade.buy({ amountPercent: 100 });
// GOOD - Always use stop losses
td.trade.buy({
amountPercent: 100,
stopLoss: td.market.price * 0.98
});
Not Checking Position Status
// BAD - Might try to open multiple positions
if (rsi < 30) {
td.trade.buy({ amountPercent: 100 });
}
// GOOD - Check if already in position
if (rsi < 30 && !td.position.hasPosition) {
td.trade.buy({ amountPercent: 100 });
}
Next Steps
- TD API Reference - Complete API documentation
- Indicators Guide - All available indicators
- Best Practices - Tips for robust strategies
- Examples - More strategy examples