redesign fully scaffolded and web login works
This commit is contained in:
198
gateway/src/harness/skills/market-analysis.ts
Normal file
198
gateway/src/harness/skills/market-analysis.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
import { BaseSkill, type SkillInput, type SkillResult, type SkillMetadata } from './base-skill.js';
|
||||
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
||||
import type { FastifyBaseLogger } from 'fastify';
|
||||
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
||||
|
||||
/**
|
||||
* Market analysis skill implementation
|
||||
*
|
||||
* See market-analysis.skill.md for full documentation
|
||||
*/
|
||||
export class MarketAnalysisSkill extends BaseSkill {
|
||||
constructor(logger: FastifyBaseLogger, model?: BaseChatModel) {
|
||||
super(logger, model);
|
||||
}
|
||||
|
||||
getMetadata(): SkillMetadata {
|
||||
return {
|
||||
name: 'market-analysis',
|
||||
description: 'Analyze market conditions for a given ticker and timeframe',
|
||||
version: '1.0.0',
|
||||
author: 'Dexorder AI Platform',
|
||||
tags: ['market-data', 'analysis', 'trading'],
|
||||
};
|
||||
}
|
||||
|
||||
getParametersSchema(): Record<string, unknown> {
|
||||
return {
|
||||
type: 'object',
|
||||
required: ['ticker', 'period'],
|
||||
properties: {
|
||||
ticker: {
|
||||
type: 'string',
|
||||
description: 'Market identifier (e.g., "BINANCE:BTC/USDT")',
|
||||
},
|
||||
period: {
|
||||
type: 'string',
|
||||
enum: ['1h', '4h', '1d', '1w'],
|
||||
description: 'Analysis period',
|
||||
},
|
||||
startTime: {
|
||||
type: 'number',
|
||||
description: 'Start timestamp in microseconds',
|
||||
},
|
||||
endTime: {
|
||||
type: 'number',
|
||||
description: 'End timestamp in microseconds',
|
||||
},
|
||||
indicators: {
|
||||
type: 'array',
|
||||
items: { type: 'string' },
|
||||
description: 'Additional indicators to include',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
validateInput(parameters: Record<string, unknown>): boolean {
|
||||
if (!parameters.ticker || typeof parameters.ticker !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (!parameters.period || typeof parameters.period !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async execute(input: SkillInput): Promise<SkillResult> {
|
||||
this.logStart(input);
|
||||
|
||||
if (!this.validateInput(input.parameters)) {
|
||||
return this.error('Invalid parameters: ticker and period are required');
|
||||
}
|
||||
|
||||
try {
|
||||
const ticker = input.parameters.ticker as string;
|
||||
const period = input.parameters.period as string;
|
||||
const indicators = (input.parameters.indicators as string[]) || [];
|
||||
|
||||
// 1. Fetch OHLC data from Iceberg
|
||||
// TODO: Implement Iceberg query
|
||||
// const ohlcData = await this.fetchOHLCData(ticker, period, startTime, endTime);
|
||||
const ohlcData = this.getMockOHLCData(); // Placeholder
|
||||
|
||||
// 2. Calculate technical indicators
|
||||
const analysis = this.calculateAnalysis(ohlcData, indicators);
|
||||
|
||||
// 3. Generate natural language analysis using LLM
|
||||
let narrativeAnalysis = '';
|
||||
if (this.model) {
|
||||
narrativeAnalysis = await this.generateNarrativeAnalysis(
|
||||
ticker,
|
||||
period,
|
||||
analysis
|
||||
);
|
||||
}
|
||||
|
||||
const result = this.success({
|
||||
ticker,
|
||||
period,
|
||||
timeRange: {
|
||||
start: ohlcData.startTime,
|
||||
end: ohlcData.endTime,
|
||||
},
|
||||
trend: analysis.trend,
|
||||
priceChange: analysis.priceChange,
|
||||
volumeProfile: analysis.volumeProfile,
|
||||
supportLevels: analysis.supportLevels,
|
||||
resistanceLevels: analysis.resistanceLevels,
|
||||
indicators: analysis.indicators,
|
||||
analysis: narrativeAnalysis,
|
||||
});
|
||||
|
||||
this.logEnd(result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
const result = this.error(error as Error);
|
||||
this.logEnd(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate technical analysis from OHLC data
|
||||
*/
|
||||
private calculateAnalysis(
|
||||
ohlcData: any,
|
||||
_requestedIndicators: string[]
|
||||
): any {
|
||||
// TODO: Implement proper technical analysis
|
||||
// This is a simplified placeholder
|
||||
|
||||
const priceChange = ((ohlcData.close - ohlcData.open) / ohlcData.open) * 100;
|
||||
const trend = priceChange > 1 ? 'bullish' : priceChange < -1 ? 'bearish' : 'neutral';
|
||||
|
||||
return {
|
||||
trend,
|
||||
priceChange,
|
||||
volumeProfile: {
|
||||
average: ohlcData.avgVolume,
|
||||
recent: ohlcData.currentVolume,
|
||||
trend: ohlcData.currentVolume > ohlcData.avgVolume ? 'increasing' : 'decreasing',
|
||||
},
|
||||
supportLevels: [ohlcData.low * 0.98, ohlcData.low * 0.95],
|
||||
resistanceLevels: [ohlcData.high * 1.02, ohlcData.high * 1.05],
|
||||
indicators: {},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate natural language analysis using LLM
|
||||
*/
|
||||
private async generateNarrativeAnalysis(
|
||||
ticker: string,
|
||||
period: string,
|
||||
analysis: any
|
||||
): Promise<string> {
|
||||
if (!this.model) {
|
||||
return 'LLM not available for narrative analysis';
|
||||
}
|
||||
|
||||
const systemPrompt = `You are a professional market analyst.
|
||||
Provide concise, actionable market analysis based on technical data.
|
||||
Focus on key insights and avoid jargon.`;
|
||||
|
||||
const userPrompt = `Analyze the following market data for ${ticker} (${period}):
|
||||
|
||||
Trend: ${analysis.trend}
|
||||
Price Change: ${analysis.priceChange.toFixed(2)}%
|
||||
Volume: ${analysis.volumeProfile.trend}
|
||||
Support Levels: ${analysis.supportLevels.join(', ')}
|
||||
Resistance Levels: ${analysis.resistanceLevels.join(', ')}
|
||||
|
||||
Provide a 2-3 sentence analysis suitable for a trading decision.`;
|
||||
|
||||
const response = await this.model.invoke([
|
||||
new SystemMessage(systemPrompt),
|
||||
new HumanMessage(userPrompt),
|
||||
]);
|
||||
|
||||
return response.content as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock OHLC data (placeholder until Iceberg integration)
|
||||
*/
|
||||
private getMockOHLCData(): any {
|
||||
return {
|
||||
startTime: Date.now() - 7 * 24 * 60 * 60 * 1000,
|
||||
endTime: Date.now(),
|
||||
open: 50000,
|
||||
high: 52000,
|
||||
low: 49000,
|
||||
close: 51500,
|
||||
avgVolume: 1000000,
|
||||
currentVolume: 1200000,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user