@gabriel3615/ta_analysis
Version:
stock ta analysis
966 lines (873 loc) • 30.4 kB
text/typescript
/**
* 集成分析编排器
* 负责协调各个分析模块的执行和结果整合
*/
import type { IntegratedTradePlan } from '../../types.js';
import type { Candle } from '../../types.js';
import { generateUniqueId } from '../../util/util.js';
import { createLogger } from '../../util/logger.js';
// 分析模块导入
import { multiTimeFrameChipDistAnalysis } from '../analyzer/chip/multiTimeFrameChipDistributionAnalysis.js';
import { analyzeMultiTimeframePattern } from '../analyzer/trendReversal/multiTimeFrameTrendReversal.js';
import { analyzeMultiTimeBBSR } from '../analyzer/sr/multiTimeFrameBBSRAnalysis.js';
import { analyzeVolumeVolatilityCombined } from '../analyzer/volatility/volatilityAnalysis.js';
import { analyzeMarketStructure } from '../analyzer/structure/structureDetector.js';
import { analyzeSupplyDemandZone } from '../analyzer/supplyDemand/sdDetector.js';
import { analyzeRange } from '../analyzer/range/rangeDetector.js';
import { analyzeTrendlinesAndChannels } from '../analyzer/trendline/trendlineDetector.js';
// 集成模块导入
import { SignalAggregator } from './SignalAggregator.js';
import { KeyLevelManager } from './KeyLevelManager.js';
import { StrategyGenerator } from './StrategyGenerator.js';
import { createChipPlugin } from './plugins/chipPlugin.js';
import { createPatternPlugin } from './plugins/patternPlugin.js';
import { createVolumePlugin } from './plugins/volumePlugin.js';
import { createBbsrPlugin } from './plugins/bbsrPlugin.js';
import { createStructurePlugin } from './plugins/structurePlugin.js';
import { createSupplyDemandPlugin } from './plugins/supplyDemandPlugin.js';
import { createRangePlugin } from './plugins/rangePlugin.js';
import { createTrendlinePlugin } from './plugins/trendlinePlugin.js';
import { DataProvider } from '../../data/DataProvider.js';
import { NarrativeBuilder } from './NarrativeBuilder.js';
import type {
AnalysisError,
AnalysisInputData,
AnalysisResultWrapper,
BatchAnalysisInput,
BatchAnalysisResult,
IntegratedAnalysisResult,
IntegrationContext,
} from './IntegrationTypes.js';
import {
DEFAULT_INTEGRATION_CONFIG,
type IntegrationConfig,
} from './IntegrationConfig.js';
export class IntegratedOrchestrator {
private signalAggregator: SignalAggregator;
private keyLevelManager: KeyLevelManager;
private strategyGenerator: StrategyGenerator;
private dataProvider = new DataProvider(100);
private narrative = new NarrativeBuilder();
private logger = createLogger('normal', '[Orchestrator]');
constructor(private config = DEFAULT_INTEGRATION_CONFIG) {
this.signalAggregator = new SignalAggregator(config);
this.keyLevelManager = new KeyLevelManager(config);
this.strategyGenerator = new StrategyGenerator(config);
this.registerBuiltInPlugins();
}
/** 统一注册内置插件,供构造与配置更新复用 */
private registerBuiltInPlugins(): void {
this.signalAggregator.registerPlugin(createChipPlugin());
this.signalAggregator.registerPlugin(createPatternPlugin());
this.signalAggregator.registerPlugin(createVolumePlugin());
this.signalAggregator.registerPlugin(createBbsrPlugin());
this.signalAggregator.registerPlugin(createStructurePlugin());
this.signalAggregator.registerPlugin(createSupplyDemandPlugin());
this.signalAggregator.registerPlugin(createRangePlugin());
this.signalAggregator.registerPlugin(createTrendlinePlugin());
}
/**
* 执行单个股票的综合分析
*/
async executeIntegratedAnalysis(
symbol: string,
customConfig?: Partial<IntegrationConfig>
): Promise<IntegratedAnalysisResult> {
const startTime = Date.now();
const executionId = generateUniqueId();
// 合并配置
const finalConfig = customConfig
? { ...this.config, ...customConfig }
: this.config;
// 创建执行上下文
const context: IntegrationContext = {
symbol,
timestamp: new Date(),
config: finalConfig,
executionId,
metadata: {
version: '2.0.0',
orchestratorType: 'enhanced',
},
};
try {
this.logger.setLevel(finalConfig.options.logLevel ?? 'normal');
this.logger.log(
`======== 开始执行 ${symbol} 综合分析 (${executionId}) ========`
);
// 获取数据
const dataStartTime = Date.now();
const { weeklyData, dailyData, hourlyData } =
await this.dataProvider.getMultiTimeframeData(symbol, finalConfig);
const dataEndTime = Date.now();
// 执行各个分析模块
const analysisStartTime = Date.now();
const analysisData = await this.executeAllAnalyses(
symbol,
weeklyData,
dailyData,
hourlyData,
context
);
const analysisEndTime = Date.now();
// 信号汇总
const signalStartTime = Date.now();
const signalResult = this.signalAggregator.aggregateSignals(
analysisData,
context
);
const signalEndTime = Date.now();
// 关键位管理
const keyLevelStartTime = Date.now();
const keyLevelResult = this.keyLevelManager.extractAndMergeKeyLevels(
analysisData,
context
);
const keyLevelEndTime = Date.now();
// 策略生成
const strategyStartTime = Date.now();
const strategyInput = {
symbol,
currentPrice: analysisData.analyses.chip.currentPrice,
signalResult,
keyLevels: keyLevelResult.mergedLevels,
analyses: analysisData.analyses,
config: finalConfig,
};
const strategyResult =
this.strategyGenerator.generateStrategy(strategyInput);
const strategyEndTime = Date.now();
// 构建最终交易计划
const tradePlan = this.buildTradePlan(
symbol,
analysisData,
signalResult,
keyLevelResult,
strategyResult,
context
);
const totalEndTime = Date.now();
const result: IntegratedAnalysisResult = {
tradePlan,
context,
performance: {
totalExecutionTime: totalEndTime - startTime,
moduleExecutionTimes: {
dataFetching: dataEndTime - dataStartTime,
analysis: analysisEndTime - analysisStartTime,
signalAggregation: signalEndTime - signalStartTime,
keyLevelManagement: keyLevelEndTime - keyLevelStartTime,
strategyGeneration: strategyEndTime - strategyStartTime,
},
cacheHitRate: this.dataProvider.stats().hitRate,
},
};
this.logger.log(
`======== ${symbol} 综合分析完成,耗时: ${result.performance.totalExecutionTime}ms ========`
);
return result;
} catch (error) {
this.logger.error(`综合分析执行失败 (${symbol}):`, error);
throw error;
}
}
/**
* 执行单个加密货币的综合分析
*/
async executeIntegratedCryptoAnalysis(
symbol: string,
customConfig?: Partial<IntegrationConfig>
): Promise<IntegratedAnalysisResult> {
const startTime = Date.now();
const executionId = generateUniqueId();
// 合并配置
const finalConfig = customConfig
? { ...this.config, ...customConfig }
: this.config;
// 创建执行上下文
const context: IntegrationContext = {
symbol,
timestamp: new Date(),
config: finalConfig,
executionId,
metadata: {
version: '2.0.0',
orchestratorType: 'enhanced',
dataSource: 'crypto',
},
};
try {
this.logger.setLevel(finalConfig.options.logLevel ?? 'normal');
this.logger.log(
`======== 开始执行(加密货币) ${symbol} 综合分析 (${executionId}) ========`
);
// 获取加密数据(遵循 lookbackDays)
const dataStartTime = Date.now();
const { weeklyData, dailyData, hourlyData } =
await this.dataProvider.getMultiTimeframeCryptoData(
symbol,
finalConfig
);
const dataEndTime = Date.now();
// 执行各个分析模块
const analysisStartTime = Date.now();
const analysisData = await this.executeAllAnalyses(
symbol,
weeklyData,
dailyData,
hourlyData,
context
);
const analysisEndTime = Date.now();
// 信号汇总
const signalStartTime = Date.now();
const signalResult = this.signalAggregator.aggregateSignals(
analysisData,
context
);
const signalEndTime = Date.now();
// 关键位管理
const keyLevelStartTime = Date.now();
const keyLevelResult = this.keyLevelManager.extractAndMergeKeyLevels(
analysisData,
context
);
const keyLevelEndTime = Date.now();
// 策略生成
const strategyStartTime = Date.now();
const strategyInput = {
symbol,
currentPrice: analysisData.analyses.chip.currentPrice,
signalResult,
keyLevels: keyLevelResult.mergedLevels,
analyses: analysisData.analyses,
config: finalConfig,
};
const strategyResult =
this.strategyGenerator.generateStrategy(strategyInput);
const strategyEndTime = Date.now();
// 构建最终交易计划
const tradePlan = this.buildTradePlan(
symbol,
analysisData,
signalResult,
keyLevelResult,
strategyResult,
context
);
const totalEndTime = Date.now();
const result: IntegratedAnalysisResult = {
tradePlan,
context,
performance: {
totalExecutionTime: totalEndTime - startTime,
moduleExecutionTimes: {
dataFetching: dataEndTime - dataStartTime,
analysis: analysisEndTime - analysisStartTime,
signalAggregation: signalEndTime - signalStartTime,
keyLevelManagement: keyLevelEndTime - keyLevelStartTime,
strategyGeneration: strategyEndTime - strategyStartTime,
},
cacheHitRate: this.dataProvider.stats().hitRate,
},
};
this.logger.log(
`======== (加密货币) ${symbol} 综合分析完成,耗时: ${result.performance.totalExecutionTime}ms ========`
);
return result;
} catch (error) {
this.logger.error(`(加密货币) 综合分析执行失败 (${symbol}):`, error);
throw error;
}
}
/**
* 执行离线综合分析,用于回测
* @param symbol - 股票代码
* @param dailyData - 日线数据
* @param weeklyData - 周线数据
* @param hourlyData - 小时线数据
* @param customConfig - 自定义配置
*/
async executeOfflineAnalysis(
symbol: string,
dailyData: Candle[],
weeklyData: Candle[],
hourlyData: Candle[],
customConfig?: Partial<IntegrationConfig>
): Promise<IntegratedAnalysisResult> {
const startTime = Date.now();
const executionId = generateUniqueId();
const finalConfig = customConfig
? { ...this.config, ...customConfig }
: this.config;
const context: IntegrationContext = {
symbol,
timestamp: new Date(),
config: finalConfig,
executionId,
metadata: {
version: '2.0.0',
orchestratorType: 'offline',
},
};
try {
this.logger.setLevel(finalConfig.options.logLevel ?? 'silent');
const analysisStartTime = Date.now();
const analysisData = await this.executeAllAnalyses(
symbol,
weeklyData,
dailyData,
hourlyData,
context
);
const analysisEndTime = Date.now();
const signalStartTime = Date.now();
const signalResult = this.signalAggregator.aggregateSignals(
analysisData,
context
);
const signalEndTime = Date.now();
const keyLevelStartTime = Date.now();
const keyLevelResult = this.keyLevelManager.extractAndMergeKeyLevels(
analysisData,
context
);
const keyLevelEndTime = Date.now();
const strategyStartTime = Date.now();
const strategyInput = {
symbol,
currentPrice: analysisData.analyses.chip.currentPrice,
signalResult,
keyLevels: keyLevelResult.mergedLevels,
analyses: analysisData.analyses,
config: finalConfig,
};
const strategyResult =
this.strategyGenerator.generateStrategy(strategyInput);
const strategyEndTime = Date.now();
const tradePlan = this.buildTradePlan(
symbol,
analysisData,
signalResult,
keyLevelResult,
strategyResult,
context
);
const totalEndTime = Date.now();
return {
tradePlan,
context,
performance: {
totalExecutionTime: totalEndTime - startTime,
moduleExecutionTimes: {
dataFetching: 0, // No data fetching in offline mode
analysis: analysisEndTime - analysisStartTime,
signalAggregation: signalEndTime - signalStartTime,
keyLevelManagement: keyLevelEndTime - keyLevelStartTime,
strategyGeneration: strategyEndTime - strategyStartTime,
},
},
};
} catch (error) {
this.logger.error(`离线分析执行失败 (${symbol}):`, error);
throw error;
}
}
/**
* 批量执行分析
*/
async executeBatchAnalysis(
input: BatchAnalysisInput
): Promise<BatchAnalysisResult> {
const startTime = Date.now();
const results = new Map<string, IntegratedAnalysisResult>();
const errors = new Map<string, AnalysisError>();
const parallelLimit = input.parallelLimit || 3;
const symbols = [...input.symbols];
// 分批处理
for (let i = 0; i < symbols.length; i += parallelLimit) {
const batch = symbols.slice(i, i + parallelLimit);
const batchPromises = batch.map(async symbol => {
try {
const result = await this.executeIntegratedAnalysis(
symbol,
input.config
);
results.set(symbol, result);
} catch (error) {
const analysisError: AnalysisError = {
code: 'BATCH_ANALYSIS_FAILED',
message:
error instanceof Error ? error.message : 'Batch analysis failed',
module: 'orchestrator',
details: error,
recoverable: true,
};
errors.set(symbol, analysisError);
}
});
await Promise.all(batchPromises);
}
const endTime = Date.now();
const totalExecutionTime = endTime - startTime;
return {
results,
summary: {
totalSymbols: input.symbols.length,
successCount: results.size,
errorCount: errors.size,
totalExecutionTime,
averageExecutionTime: totalExecutionTime / input.symbols.length,
},
errors,
};
}
/**
* 执行所有分析模块
*/
private async executeAllAnalyses(
symbol: string,
weeklyData: Candle[],
dailyData: Candle[],
hourlyData: Candle[],
context: IntegrationContext
): Promise<AnalysisInputData> {
const config = context.config;
this.logger.setLevel(config.options.logLevel ?? 'normal');
this.logger.verbose('正在执行各分析模块...');
try {
// 并行执行分析(仅保留并行逻辑)
const [
chipAnalysis,
patternAnalysis,
bbsrAnalysis,
volatilityAnalysis,
structureAnalysis,
supplyDemandAnalysis,
rangeAnalysis,
trendlineAnalysis,
] = await Promise.all([
this.executeWithFallback(
() =>
multiTimeFrameChipDistAnalysis(
symbol,
'daily',
['weekly', 'daily', '1hour'],
{ weekly: 0.3, daily: 0.5, '1hour': 0.2 },
weeklyData,
dailyData,
hourlyData
),
'chip'
),
this.executeWithFallback(
() => analyzeMultiTimeframePattern(weeklyData, dailyData, hourlyData),
'pattern'
),
this.executeWithFallback(
() => analyzeMultiTimeBBSR(symbol, dailyData, hourlyData),
'bbsr'
),
this.executeWithFallback(
() =>
analyzeVolumeVolatilityCombined(
(hourlyData?.length ?? 0) >= 20 ? hourlyData : dailyData
),
'volatility'
),
this.executeWithFallback(
() => analyzeMarketStructure(dailyData, 'daily'),
'structure'
),
this.executeWithFallback(
() => analyzeSupplyDemandZone(symbol, dailyData, 'daily'),
'supplyDemand'
),
this.executeWithFallback(
() => analyzeRange(symbol, dailyData, 'daily'),
'range'
),
this.executeWithFallback(
() => analyzeTrendlinesAndChannels(symbol, dailyData, 'daily'),
'trendline'
),
]);
return {
symbol,
analyses: {
chip: chipAnalysis.data!,
pattern: patternAnalysis.data!,
volatility: volatilityAnalysis.data!,
bbsr: bbsrAnalysis.data!,
structure: structureAnalysis.data!,
supplyDemand: supplyDemandAnalysis.data!,
range: rangeAnalysis.data!,
trendline: trendlineAnalysis.data!,
},
};
} catch (error) {
throw new Error(
`分析模块执行失败: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
}
/**
* 带降级策略的执行包装器
*/
private async executeWithFallback<T>(
analysisFunction: () => Promise<T> | T,
moduleName: string
): Promise<AnalysisResultWrapper<T>> {
const startTime = Date.now();
try {
const result = await analysisFunction();
return {
success: true,
data: result,
executionTime: Date.now() - startTime,
};
} catch (error) {
const analysisError: AnalysisError = {
code: `${moduleName.toUpperCase()}_FAILED`,
message: error instanceof Error ? error.message : 'Analysis failed',
module: moduleName,
details: error,
recoverable: true,
};
// 如果启用了降级策略,返回基础结果
if (this.config.options.enableFallbackStrategy) {
const fallbackData = this.createFallbackData(moduleName) as T;
return {
success: false,
error: analysisError,
fallback: fallbackData,
data: fallbackData,
executionTime: Date.now() - startTime,
};
}
throw error;
}
}
/**
* 创建降级数据
*/
private createFallbackData(moduleName: string): any {
switch (moduleName) {
case 'chip':
return {
symbol: 'UNKNOWN',
currentPrice: 0,
combinedBuySignalStrength: 50,
combinedShortSignalStrength: 50,
majorSupportLevels: [],
majorResistanceLevels: [],
strongSupportLevels: [],
strongResistanceLevels: [],
primaryTimeframe: 'daily',
};
case 'pattern':
return {
combinedSignal: 'neutral',
signalStrength: 0,
reversalSignals: [],
};
case 'volatility':
return {
volumeAnalysis: {
volumeAnalysis: {
adLine: [],
adSlope: 0,
adTrend: 'neutral',
divergence: {
type: 'none',
strength: 0,
description: 'fallback',
},
volumeForce: 0,
moneyFlowIndex: 0,
chaikinOscillator: 0,
obv: [],
obvSlope: 0,
volumePriceConfirmation: false,
summary: 'fallback',
},
formattedVolumeAnalysis: 'fallback',
},
volumeAnalysisReason: 'fallback',
volatilityAnalysis: {
volatilityAnalysis: {
historicalVolatility: 0,
bollingerBandWidth: 0,
atr: 0,
atrPercent: 0,
volatilityRegime: 'medium',
isVolatilityIncreasing: false,
volatilityPercentile: 0,
volatilityTrend: 'stable',
recentRanges: { daily: 0, weekly: 0, monthly: 0 },
riskMetrics: { maxDrawdown: 0, downsideDeviation: 0 },
},
formattedVolatilityAnalysis: 'fallback',
},
volatilityAnalysisReason: 'fallback',
combinedAnalysisSummary: 'fallback',
};
// ... 其他模块的降级数据
default:
return {};
}
}
/**
* 构建交易计划
*/
private buildTradePlan(
symbol: string,
analysisData: AnalysisInputData,
signalResult: any,
keyLevelResult: any,
strategyResult: any,
context: IntegrationContext
): IntegratedTradePlan {
// 构建完整的交易计划
return {
symbol,
currentPrice: analysisData.analyses.chip.currentPrice,
date: context.timestamp,
direction: signalResult.direction,
signalStrength: signalResult.signalStrength,
confidenceScore: signalResult.confidenceScore,
// 权重信息
chipAnalysisWeight: context.config.weights.chip,
patternAnalysisWeight: context.config.weights.pattern,
volumeAnalysisWeight: context.config.weights.volume,
bbsrAnalysisWeight: context.config.weights.bbsr,
// 贡献度
chipAnalysisContribution: signalResult.contributions.chip,
patternAnalysisContribution: signalResult.contributions.pattern,
volumeAnalysisContribution: signalResult.contributions.volume,
bbsrAnalysisContribution: signalResult.contributions.bbsr,
// 策略相关
entryStrategy: strategyResult.entryStrategy,
exitStrategy: strategyResult.exitStrategy,
riskManagement: strategyResult.riskManagement,
// 关键信息
keyLevels: keyLevelResult.mergedLevels,
confirmationSignals: strategyResult.confirmationSignals,
invalidationConditions: strategyResult.invalidationConditions,
keyObservations: strategyResult.keyObservations,
warnings: strategyResult.warnings,
// 分析相关
bbsrAnalysis: analysisData.analyses.bbsr,
// 新增字段
summary: this.narrative.buildSummary(signalResult),
primaryRationale: this.narrative.buildPrimaryRationale(
signalResult,
analysisData.analyses
),
secondaryRationale: this.narrative.buildSecondaryRationale(
analysisData.analyses
),
primaryTimeframe: analysisData.analyses.chip?.primaryTimeframe ?? 'daily',
timeframeConsistency: this.calculateTimeframeConsistency(analysisData),
shortTermOutlook: this.narrative.buildShortTermOutlook(
analysisData.analyses
),
mediumTermOutlook: this.narrative.buildMediumTermOutlook(
analysisData.analyses
),
longTermOutlook: this.narrative.buildLongTermOutlook(
analysisData.analyses
),
trendReversalInfo: this.extractTrendReversalInfo(
analysisData.analyses.pattern
),
vvInsights: {
volumeAnalysisReason:
analysisData.analyses.volatility.volumeAnalysisReason || '',
volatilityAnalysisReason:
analysisData.analyses.volatility.volatilityAnalysisReason || '',
combinedAnalysisSummary:
analysisData.analyses.volatility.combinedAnalysisSummary || '',
},
summaries: this.narrative.buildSummariesFromPlugins(
this.signalAggregator.getPlugins(),
analysisData,
context
),
};
}
/**
* 创建降级交易计划
*/
private createFallbackTradePlan(
symbol: string,
context: IntegrationContext
): IntegratedTradePlan {
return {
symbol,
currentPrice: 0,
date: context.timestamp,
direction: 'neutral' as any,
signalStrength: 'none' as any,
confidenceScore: 0,
chipAnalysisWeight: 0.25,
patternAnalysisWeight: 0.35,
volumeAnalysisWeight: 0.25,
bbsrAnalysisWeight: 0.15,
chipAnalysisContribution: 0,
patternAnalysisContribution: 0,
volumeAnalysisContribution: 0,
bbsrAnalysisContribution: 0,
entryStrategy: {
idealEntryPrice: 0,
alternativeEntryPrice: 0,
entryType: 'immediate',
entryConditions: [],
priceZones: { ideal: [0, 0], acceptable: [0, 0] },
timeWindow: 'N/A',
riskLevel: 'medium' as any,
},
exitStrategy: {
takeProfitLevels: [],
stopLossLevels: [],
timeBasedExit: 'N/A',
maximumHoldingPeriod: 'N/A',
},
riskManagement: {
suggestionPosition: 0,
riskRewardRatio: 0,
maxLoss: 'N/A',
volatilityConsideration: 'N/A',
adjustmentTriggers: [],
},
keyLevels: [],
confirmationSignals: [],
invalidationConditions: [],
keyObservations: ['分析执行失败,使用降级模式'],
warnings: ['分析模块执行失败,建议手动验证'],
bbsrAnalysis: {} as any,
summary: '分析失败,无法生成摘要',
primaryRationale: '分析失败,无法确定主要逻辑',
secondaryRationale: '分析失败,无法确定次要逻辑',
primaryTimeframe: 'daily',
timeframeConsistency: '0%',
shortTermOutlook: '无法确定',
mediumTermOutlook: '无法确定',
longTermOutlook: '无法确定',
trendReversalInfo: { hasReversalSignal: false, description: '无法检测' },
vvInsights: {
volumeAnalysisReason: '分析失败',
volatilityAnalysisReason: '分析失败',
combinedAnalysisSummary: '分析失败',
},
summaries: {
chipSummary: '分析失败',
patternSummary: '分析失败',
bbsrSummary: '分析失败',
vvSummary: '分析失败',
structureSummary: '分析失败',
supplyDemandSummary: '分析失败',
rangeSummary: '分析失败',
trendlineSummary: '分析失败',
},
};
}
/**
* 计算时间周期一致性
*/
private calculateTimeframeConsistency(
analysisData: AnalysisInputData
): string {
const cfg = this.config.consistency;
const pattern: any = analysisData.analyses.pattern;
// 形态多周期方向按权重折算为分数(多头=1,空头=-1,缺省=0)
let patternScore = 0;
const tfAnalyses = pattern?.timeframeAnalyses as
| { timeframe: 'weekly' | 'daily' | '1hour'; patternSignal?: string }[]
| undefined;
if (Array.isArray(tfAnalyses)) {
for (const tf of tfAnalyses) {
const w = cfg.timeframeWeights[tf.timeframe] ?? 0;
if (tf.patternSignal === 'bullish') patternScore += 1 * w;
else if (tf.patternSignal === 'bearish') patternScore += -1 * w;
}
}
// 结构趋势辅助
const structure = analysisData.analyses.structure;
if (structure?.trend === 'up')
patternScore += 1 * (cfg.structureWeight ?? 0);
else if (structure?.trend === 'down')
patternScore += -1 * (cfg.structureWeight ?? 0);
// 趋势线斜率辅助
const tl: any = analysisData.analyses.trendline;
if (tl?.channel?.slope > 0) patternScore += 1 * (cfg.trendlineWeight ?? 0);
else if (tl?.channel?.slope < 0)
patternScore += -1 * (cfg.trendlineWeight ?? 0);
// 归一化到 0-100%,绝对值越接近1一致性越高
const maxPossible =
(cfg.timeframeWeights.weekly ?? 0) +
(cfg.timeframeWeights.daily ?? 0) +
(cfg.timeframeWeights['1hour'] ?? 0) +
(cfg.structureWeight ?? 0) +
(cfg.trendlineWeight ?? 0);
if (maxPossible <= 0) return '0%';
const ratio = Math.min(1, Math.abs(patternScore) / maxPossible);
return `${Math.round(ratio * 100)}%`;
}
/**
* 提取趋势反转信息
*/
private extractTrendReversalInfo(patternAnalysis: any): any {
// 优先使用增强的趋势逆转信号(如存在)
const primary = patternAnalysis?.primaryReversalSignal;
const signals = patternAnalysis?.reversalSignals as any[] | undefined;
if (primary) {
const dir =
primary.direction > 0
? '看多'
: primary.direction < 0
? '看空'
: '中性';
return {
hasReversalSignal: !!primary.isReversal,
description: `检测到${dir}逆转信号,强度${Math.round(primary.reversalStrength ?? 0)},小周期: ${primary.smallTimeframe} 对 大周期: ${primary.largeTimeframe}`,
targets: primary.targets ?? undefined,
};
}
if (Array.isArray(signals) && signals.length > 0) {
const best = [...signals].sort(
(a, b) => (b.reversalStrength ?? 0) - (a.reversalStrength ?? 0)
)[0];
const dir =
best.direction > 0 ? '看多' : best.direction < 0 ? '看空' : '中性';
return {
hasReversalSignal: !!best.isReversal,
description: `检测到${dir}逆转信号,强度${Math.round(best.reversalStrength ?? 0)},小周期: ${best.smallTimeframe} 对 大周期: ${best.largeTimeframe}`,
targets: best.targets ?? undefined,
};
}
// 退化:根据综合形态方向给出提示
const combined = patternAnalysis?.combinedSignal;
if (combined === 'bullish' || combined === 'bearish') {
return {
hasReversalSignal: false,
description: `当前形态综合方向为${combined === 'bullish' ? '看多' : '看空'},未形成明确的逆转模板`,
};
}
return { hasReversalSignal: false, description: '未检测到趋势反转信号' };
}
// 摘要与叙述构建已下沉到 NarrativeBuilder
// 展望构建已下沉到 NarrativeBuilder
/**
* 更新配置
*/
updateConfig(newConfig: Partial<IntegrationConfig>): void {
this.config = { ...this.config, ...newConfig };
// 更新子模块配置
this.signalAggregator = new SignalAggregator(this.config);
this.keyLevelManager = new KeyLevelManager(this.config);
this.strategyGenerator = new StrategyGenerator(this.config);
this.registerBuiltInPlugins();
}
// 缓存统计如需对外暴露,可直接使用 this.dataCache.stats()
}