Quick Reference
Essential concepts for writing Kronos strategies.
The Kronos Context
Every strategy has access to the Kronos SDK through k:
type MyStrategy struct {
strategy.BaseStrategy
k kronos.Kronos // Your gateway to everything
}
The k instance provides:
k.Asset(symbol)- Get asset referencesk.Indicators- Technical indicatorsk.Market- Market data (prices, order books, funding)k.Analytics- Market analyticsk.Log()- Structured logging
Assets
Get references to assets you want to trade:
btc := s.k.Asset("BTC")
eth := s.k.Asset("ETH")
sol := s.k.Asset("SOL")
Assets are just references. Kronos knows which exchange to use based on your config.
Indicators
All indicators follow the same pattern: pass the asset and parameters.
// RSI - Relative Strength Index
rsi := s.k.Indicators().RSI(btc, 14)
// SMA - Simple Moving Average
sma := s.k.Indicators().SMA(btc, 20)
// EMA - Exponential Moving Average
ema := s.k.Indicators().EMA(btc, 50)
// MACD - Moving Average Convergence Divergence
macd := s.k.Indicators().MACD(btc, 12, 26, 9)
s.k.Log().Debug("MACD", btc.Symbol(), "MACD: %s, Signal: %s, Histogram: %s",
macd.MACD, macd.Signal, macd.Histogram)
// Bollinger Bands
bb := s.k.Indicators().BollingerBands(btc, 20, 2.0)
s.k.Log().Debug("BB", btc.Symbol(), "Upper: %s, Middle: %s, Lower: %s",
bb.Upper, bb.Middle, bb.Lower)
// Stochastic Oscillator
stoch := s.k.Indicators().Stochastic(btc, 14, 3)
s.k.Log().Debug("Stochastic", btc.Symbol(), "K: %s, D: %s", stoch.K, stoch.D)
// ATR - Average True Range
atr := s.k.Indicators().ATR(btc, 14)
Kronos automatically:
- Fetches the required price data
- Calculates the indicator
- Returns the latest value
Indicator Options
Specify exchange or interval when needed:
import "github.com/backtesting-org/kronos-sdk/pkg/kronos/indicators"
import "github.com/backtesting-org/kronos-sdk/pkg/types/connector"
// Use specific exchange
rsi := s.k.Indicators().RSI(btc, 14, indicators.IndicatorOptions{
Exchange: connector.Binance,
})
// Use different timeframe
sma := s.k.Indicators().SMA(btc, 200, indicators.IndicatorOptions{
Interval: "4h",
})
// Both
ema := s.k.Indicators().EMA(btc, 50, indicators.IndicatorOptions{
Exchange: connector.Bybit,
Interval: "1h",
})
Market Data
Access real-time market data:
// Current price
price := s.k.Market().Price(btc)
// Price from specific exchange
price := s.k.Market().Price(btc, market.MarketOptions{
Exchange: connector.Binance,
})
// Prices from all exchanges
prices := s.k.Market().Prices(btc)
for exchange, price := range prices {
s.k.Log().Info("%s: %s", exchange, price)
}
// Order book
book := s.k.Market().OrderBook(btc)
topBid := book.Bids[0] // Best bid
topAsk := book.Asks[0] // Best ask
// Funding rate (perpetuals)
funding := s.k.Market().FundingRate(btc)
// Historical klines
klines := s.k.Market().Klines(btc, "1h", 100) // Last 100 1h candles
Signals
Create trading signals with the fluent API:
import "github.com/backtesting-org/kronos-sdk/pkg/types/connector"
// Buy signal - specify asset, exchange, and quantity
signal := s.k.Signal(s.GetName()).
Buy(btc, connector.Binance, decimal.NewFromFloat(0.1)).
Build()
// Sell signal
signal := s.k.Signal(s.GetName()).
Sell(btc, connector.Binance, decimal.NewFromFloat(0.1)).
Build()
// Short sell signal
signal := s.k.Signal(s.GetName()).
SellShort(btc, connector.Binance, decimal.NewFromFloat(0.1)).
Build()
// Limit orders with specific price
signal := s.k.Signal(s.GetName()).
BuyLimit(btc, connector.Binance, decimal.NewFromFloat(0.1), decimal.NewFromInt(45000)).
Build()
// Multiple trades in one signal (e.g., cash and carry)
signal := s.k.Signal(s.GetName()).
Buy(btc, connector.Binance, decimal.NewFromFloat(0.1)).
SellShort(btc, connector.Bybit, decimal.NewFromFloat(0.1)).
Build()
Return signals from GetSignals():
func (s *Strategy) GetSignals() ([]*strategy.Signal, error) {
btc := s.k.Asset("BTC")
rsi := s.k.Indicators().RSI(btc, 14)
if rsi.LessThan(decimal.NewFromInt(30)) {
signal := s.k.Signal(s.GetName()).
Buy(btc, connector.Binance, decimal.NewFromFloat(0.1)).
Build()
return []*strategy.Signal{signal}, nil
}
return nil, nil
}
Working with Decimals
Kronos uses decimal.Decimal for all financial calculations:
import "github.com/shopspring/decimal"
// Create decimals
price := decimal.NewFromFloat(50000.50)
quantity := decimal.NewFromInt(2)
pct := decimal.NewFromString("0.025") // 2.5%
// Math operations
total := price.Mul(quantity)
fee := total.Mul(pct)
net := total.Sub(fee)
// Comparisons
if price.GreaterThan(decimal.NewFromInt(50000)) {
// Price above 50k
}
if rsi.LessThan(decimal.NewFromInt(30)) {
// RSI oversold
}
// String conversion
s.k.Log().Info("Price: %s", price.String()) // "50000.5"
s.k.Log().Info("Price fixed: %s", price.StringFixed(2)) // "50000.50"
Never use float64 for money
Always use decimal.Decimal to avoid floating-point precision errors.
Logging
Use structured logging to track your strategy:
// Info level
s.k.Log().Info("Strategy initialized")
// Debug level
s.k.Log().Debug("Strategy", btc.Symbol(), "RSI: %s", rsi)
// Market conditions
s.k.Log().MarketCondition("Price: %s, RSI: %s", price, rsi)
// Opportunities
s.k.Log().Opportunity("Strategy", btc.Symbol(),
"Buy signal - RSI oversold at %s", rsi)
// Failures
s.k.Log().Failed("Strategy", btc.Symbol(),
"Failed to calculate RSI: %v", err)
Error Handling
Always handle errors properly:
func (s *Strategy) GetSignals() ([]*strategy.Signal, error) {
btc := s.k.Asset("BTC")
// Check if indicators have valid data
rsi := s.k.Indicators().RSI(btc, 14)
if rsi.IsZero() {
// No data yet, skip this cycle
return nil, nil
}
// Your logic here...
return signals, nil
}
Complete Example
A simple RSI strategy:
package main
import (
"github.com/backtesting-org/kronos-sdk/pkg/types/kronos"
"github.com/backtesting-org/kronos-sdk/pkg/types/strategy"
"github.com/shopspring/decimal"
)
type RSIStrategy struct {
strategy.BaseStrategy
k kronos.Kronos
}
func NewRSI(k kronos.Kronos) strategy.Strategy {
return &RSIStrategy{k: k}
}
func (s *RSIStrategy) GetSignals() ([]*strategy.Signal, error) {
btc := s.k.Asset("BTC")
// Get RSI - Kronos handles everything
rsi := s.k.Indicators().RSI(btc, 14)
// Buy when oversold
if rsi.LessThan(decimal.NewFromInt(30)) {
return []*strategy.Signal{
s.Signal().
Buy(btc).
Quantity(decimal.NewFromFloat(0.1)).
Reason("RSI oversold at " + rsi.String()).
Build(),
}, nil
}
// Sell when overbought
if rsi.GreaterThan(decimal.NewFromInt(70)) {
return []*strategy.Signal{
s.Signal().
Sell(btc).
Quantity(decimal.NewFromFloat(0.1)).
Reason("RSI overbought at " + rsi.String()).
Build(),
}, nil
}
return nil, nil
}
// Required interface methods
func (s *RSIStrategy) GetName() strategy.StrategyName {
return "RSI"
}
func (s *RSIStrategy) GetDescription() string {
return "Simple RSI momentum strategy"
}
func (s *RSIStrategy) GetRiskLevel() strategy.RiskLevel {
return strategy.RiskLevelMedium
}
func (s *RSIStrategy) GetStrategyType() strategy.StrategyType {
return strategy.StrategyTypeTechnical
}
Next Steps
- Writing Strategies - Deep dive into strategy patterns
- Examples - Common strategy implementations
- Indicators Reference - Full indicator documentation