import { createSuccessResponse, createErrorResponse } from '../utils/helpers.js';
import { analyzeTechnicals, TA_THRESHOLDS } from '../indicators/technical-indicators.js';
import {
AnalyzeSymbolTASchema,
GetIndicatorSchema
} from '../schemas/index.js';
import {
calculateRSI,
calculateMACD,
calculateEMA,
calculateBollinger,
calculateStochastic
} from '../indicators/technical-indicators.js';
export function createTATools(exchange, mode) {
return {
analyze_symbol_ta: {
description: 'Run full technical analysis on a symbol using RSI, MACD, EMA, Bollinger Bands, and Stochastic. Returns buy/sell/hold recommendation with confidence score.',
inputSchema: AnalyzeSymbolTASchema,
handler: async (input) => {
const timeframe = input.timeframe || '1h';
const limit = input.limit || 100;
const ohlcv = await exchange.getOHLCV(input.symbol, timeframe, limit);
if (!ohlcv || ohlcv.length < TA_THRESHOLDS.MIN_CANDLES) {
return createErrorResponse(
'INSUFFICIENT_DATA',
`Need ${TA_THRESHOLDS.MIN_CANDLES} candles, got ${ohlcv?.length || 0}`
);
}
const analysis = analyzeTechnicals(ohlcv);
return createSuccessResponse({
symbol: input.symbol,
timeframe,
...analysis,
timestamp: new Date().toISOString()
}, mode);
}
},
get_indicator: {
description: 'Get a specific technical indicator value (rsi, macd, ema, bollinger, stochastic)',
inputSchema: GetIndicatorSchema,
handler: async (input) => {
const timeframe = input.timeframe || '1h';
const ohlcv = await exchange.getOHLCV(input.symbol, timeframe, 100);
if (!ohlcv || ohlcv.length < TA_THRESHOLDS.MIN_CANDLES) {
return createErrorResponse(
'INSUFFICIENT_DATA',
`Need ${TA_THRESHOLDS.MIN_CANDLES} candles, got ${ohlcv?.length || 0}`
);
}
const closes = ohlcv.map(c => c.close);
const highs = ohlcv.map(c => c.high);
const lows = ohlcv.map(c => c.low);
let result;
switch (input.indicator) {
case 'rsi':
result = calculateRSI(closes, input.period || 14);
break;
case 'macd':
result = calculateMACD(closes);
break;
case 'ema':
result = calculateEMA(closes);
break;
case 'bollinger':
result = calculateBollinger(closes, input.period || 20);
break;
case 'stochastic':
result = calculateStochastic(highs, lows, closes);
break;
default:
return createErrorResponse('INVALID_INDICATOR', `Unknown indicator: ${input.indicator}`);
}
return createSuccessResponse({
symbol: input.symbol,
timeframe,
indicator: input.indicator,
...result,
timestamp: new Date().toISOString()
}, mode);
}
}
};
}