@gabriel3615/ta_analysis
Version:
stock ta analysis
85 lines (84 loc) • 3.16 kB
JavaScript
import { structureConfig } from './structureConfig.js';
export function formatAndPrintStructureResult(result) {
console.log(`\n===== ${result.symbol} 结构分析 =====`);
console.log(`综合趋势: ${translateTrend(result.combinedTrend)} | 一致性: ${result.consistency}`);
console.log(`概述: ${result.combinedSummary}`);
const printTf = (r) => {
console.log(`\n----- ${r.timeframe} -----`);
console.log(`趋势: ${translateTrend(r.trend)}${r.lastEvent ? ` | 事件: ${translateEvent(r.lastEvent)}` : ''}`);
const suggestion = buildSuggestion(r);
if (suggestion) {
console.log(`建议: ${suggestion}`);
}
if (r.keyLevels?.length) {
console.log(`关键结构位: ${r.keyLevels.map(p => p.toFixed(2)).join(', ')}`);
}
console.log(r.summary);
};
result.results.forEach(printTf);
}
function translateTrend(t) {
return t === 'up' ? '上涨' : t === 'down' ? '下跌' : '震荡';
}
function translateEvent(e) {
const dir = e.direction === 'bullish'
? '(看涨)'
: e.direction === 'bearish'
? '(看跌)'
: '';
switch (e.type) {
case 'BOS':
return `结构突破${dir}`;
case 'CHOCH':
return `性格转换${dir}`;
case 'EqualHighs':
return '等高';
case 'EqualLows':
return '等低';
default:
return e.type;
}
}
function buildSuggestion(r) {
if (!r.keyLevels || r.keyLevels.length < 2)
return null;
const lastHigh = r.keyLevels[0];
const lastLow = r.keyLevels[1];
const offset = structureConfig.thresholds.breakThresholdPercent;
// 若趋势为震荡但存在事件方向,则用事件方向作为临时趋势
let trend = r.trend;
if (trend === 'sideways' &&
r.lastEvent &&
r.lastEvent.direction !== 'neutral') {
trend = r.lastEvent.direction === 'bullish' ? 'up' : 'down';
}
if (trend === 'up') {
const entry = lastLow;
const stop = lastLow * (1 - offset);
const target = lastHigh;
const rr = computeRR(entry, stop, target);
if (!isFinite(rr) || rr <= 0)
return null;
return `回踩 ${entry.toFixed(2)} 做多,止损 ${stop.toFixed(2)},目标 ${target.toFixed(2)},RR≈${rr.toFixed(2)}`;
}
if (trend === 'down') {
const entry = lastHigh;
const stop = lastHigh * (1 + offset);
const target = lastLow;
const rr = computeRRShort(entry, stop, target);
if (!isFinite(rr) || rr <= 0)
return null;
return `反弹至 ${entry.toFixed(2)} 做空,止损 ${stop.toFixed(2)},目标 ${target.toFixed(2)},RR≈${rr.toFixed(2)}`;
}
return null;
}
function computeRR(entry, stop, target) {
const risk = Math.max(1e-8, entry - stop);
const reward = Math.max(0, target - entry);
return reward / risk;
}
function computeRRShort(entry, stop, target) {
const risk = Math.max(1e-8, stop - entry);
const reward = Math.max(0, entry - target);
return reward / risk;
}