goldenChat base source add
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* 보조지표 설정 — 숫자 파라미터 허용 범위·드롭다운 목록
|
||||
*/
|
||||
|
||||
export interface NumericParamSpec {
|
||||
min: number;
|
||||
max: number;
|
||||
step: number;
|
||||
allowNegative: boolean;
|
||||
decimal: boolean;
|
||||
/** 드롭다운에 표시할 허용 값 목록 */
|
||||
options: number[];
|
||||
}
|
||||
|
||||
const COMMON_PERIODS = [
|
||||
1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 20, 21, 24, 26, 28, 34,
|
||||
50, 52, 60, 72, 90, 100, 120, 200,
|
||||
];
|
||||
|
||||
const DECIMAL_MULT = [0.1, 0.2, 0.25, 0.5, 0.75, 1, 1.5, 2, 2.5, 3, 4, 5];
|
||||
|
||||
function roundTo(v: number, decimals: number): number {
|
||||
const f = 10 ** decimals;
|
||||
return Math.round(v * f) / f;
|
||||
}
|
||||
|
||||
function mergeOptions(
|
||||
min: number,
|
||||
max: number,
|
||||
step: number,
|
||||
decimal: boolean,
|
||||
presets: number[],
|
||||
maxCount = 56,
|
||||
include?: number,
|
||||
): number[] {
|
||||
const set = new Set<number>();
|
||||
const dec = decimal ? (step < 1 ? 2 : 1) : 0;
|
||||
for (const p of presets) {
|
||||
if (p >= min && p <= max) set.add(roundTo(p, dec));
|
||||
}
|
||||
if (include != null && !isNaN(include) && include >= min && include <= max) {
|
||||
set.add(roundTo(include, dec));
|
||||
}
|
||||
for (let v = min; v <= max + step * 0.001 && set.size < maxCount; v += step) {
|
||||
set.add(roundTo(v, dec));
|
||||
}
|
||||
return Array.from(set).sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
function isPeriodKey(key: string): boolean {
|
||||
return /^(length|len|period\d*|kLength|dSmoothing|smooth|adxSmoothing|diLength|ccilength|turbolen|signalLength|fastLength|slowLength|longLength|shortLength|maLength|ultraLength|midLength|longLength|displacement|conversionPeriods|basePeriods|laggingSpan2Periods|length1|length2|length3|lengthRSI|lengthStoch|rsiLength|upDownLength|rocLength|stdevLength|atrLength|p|q|x)$/i.test(key);
|
||||
}
|
||||
|
||||
function isMultKey(key: string): boolean {
|
||||
return /^(mult|multiplier|percent|bbMult)$/i.test(key);
|
||||
}
|
||||
|
||||
function isOffsetKey(key: string): boolean {
|
||||
return /^offset$/i.test(key);
|
||||
}
|
||||
|
||||
function isSigmaKey(key: string): boolean {
|
||||
return /^sigma$/i.test(key);
|
||||
}
|
||||
|
||||
/** 지표 파라미터 키별 숫자 스펙 */
|
||||
export function getNumericParamSpec(
|
||||
indicatorType: string,
|
||||
paramKey: string,
|
||||
currentValue?: number,
|
||||
): NumericParamSpec {
|
||||
if (isPeriodKey(paramKey)) {
|
||||
const max = paramKey === 'rocLength' ? 200 : 500;
|
||||
return {
|
||||
min: 1,
|
||||
max,
|
||||
step: 1,
|
||||
allowNegative: false,
|
||||
decimal: false,
|
||||
options: mergeOptions(1, max, 1, false, COMMON_PERIODS, 56, currentValue),
|
||||
};
|
||||
}
|
||||
|
||||
if (isMultKey(paramKey)) {
|
||||
const isPercent = paramKey === 'percent';
|
||||
return {
|
||||
min: isPercent ? 0.01 : 0.1,
|
||||
max: isPercent ? 1 : 10,
|
||||
step: isPercent ? 0.01 : 0.1,
|
||||
allowNegative: false,
|
||||
decimal: true,
|
||||
options: mergeOptions(
|
||||
isPercent ? 0.01 : 0.1,
|
||||
isPercent ? 1 : 10,
|
||||
isPercent ? 0.01 : 0.1,
|
||||
true,
|
||||
isPercent
|
||||
? [0.05, 0.1, 0.15, 0.2, 0.25, 0.5, 0.75, 1]
|
||||
: DECIMAL_MULT,
|
||||
40,
|
||||
currentValue,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if (isOffsetKey(paramKey)) {
|
||||
if (indicatorType === 'ALMA') {
|
||||
return {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.05,
|
||||
allowNegative: false,
|
||||
decimal: true,
|
||||
options: mergeOptions(0, 1, 0.05, true, [0, 0.5, 0.85, 1], 24, currentValue),
|
||||
};
|
||||
}
|
||||
return {
|
||||
min: -500,
|
||||
max: 500,
|
||||
step: 1,
|
||||
allowNegative: true,
|
||||
decimal: false,
|
||||
options: mergeOptions(-500, 500, 1, false, [-26, -9, 0, 9, 26], 48, currentValue),
|
||||
};
|
||||
}
|
||||
|
||||
if (isSigmaKey(paramKey)) {
|
||||
return {
|
||||
min: 1,
|
||||
max: 30,
|
||||
step: 1,
|
||||
allowNegative: false,
|
||||
decimal: false,
|
||||
options: mergeOptions(1, 30, 1, false, [4, 6, 8, 10, 14, 20], 30, currentValue),
|
||||
};
|
||||
}
|
||||
|
||||
// SMI 등 소수 오실레이터 임계
|
||||
if (indicatorType === 'SMIErgodic' || indicatorType === 'SMIErgodicOscillator') {
|
||||
return {
|
||||
min: 1,
|
||||
max: 100,
|
||||
step: 1,
|
||||
allowNegative: false,
|
||||
decimal: false,
|
||||
options: mergeOptions(1, 100, 1, false, [5, 10, 20, 40], 40, currentValue),
|
||||
};
|
||||
}
|
||||
|
||||
// 기본: 정수 1~100
|
||||
return {
|
||||
min: 1,
|
||||
max: 500,
|
||||
step: 1,
|
||||
allowNegative: false,
|
||||
decimal: false,
|
||||
options: mergeOptions(1, 500, 1, false, COMMON_PERIODS, 56, currentValue),
|
||||
};
|
||||
}
|
||||
|
||||
/** 수평선(과열/침체) 기준값 */
|
||||
export function getHlinePriceSpec(indicatorType: string, current: number): NumericParamSpec {
|
||||
const byType: Record<string, number[]> = {
|
||||
RSI: [20, 30, 50, 70, 80],
|
||||
Stochastic: [20, 50, 80],
|
||||
StochRSI: [20, 50, 80],
|
||||
CCI: [-200, -100, 0, 100, 200],
|
||||
WilliamsPercentRange: [-80, -50, -20],
|
||||
MACD: [-50, 0, 50],
|
||||
ADX: [20, 25, 40],
|
||||
DMI: [10, 20, 30],
|
||||
TRIX: [-0.05, -0.01, 0, 0.01, 0.05],
|
||||
MOM: [-50, 0, 50],
|
||||
ROC: [-20, 0, 20],
|
||||
CMO: [-50, 0, 50],
|
||||
DPO: [-100, 0, 100],
|
||||
FisherTransform: [-2.5, 0, 2.5],
|
||||
SMIErgodic: [-0.4, 0, 0.4],
|
||||
SMIErgodicOscillator: [-0.4, 0, 0.4],
|
||||
Disparity: [90, 95, 100, 105, 110],
|
||||
VR: [50, 100, 150, 200, 250],
|
||||
Psychological: [25, 50, 75],
|
||||
NewPsychological: [25, 50, 75],
|
||||
InvestPsychological: [25, 50, 75],
|
||||
};
|
||||
|
||||
const presets = byType[indicatorType] ?? [-200, -100, 0, 100, 200];
|
||||
const allowNegative = presets.some(p => p < 0) || indicatorType !== 'RSI';
|
||||
const min = Math.min(-500, ...presets, current) - 50;
|
||||
const max = Math.max(500, ...presets, current) + 50;
|
||||
|
||||
return {
|
||||
min,
|
||||
max,
|
||||
step: 1,
|
||||
allowNegative: true,
|
||||
decimal: true,
|
||||
options: mergeOptions(min, max, allowNegative ? 10 : 5, true, presets, 48, current),
|
||||
};
|
||||
}
|
||||
|
||||
export function getLineWidthSpec(min = 1, max = 5): NumericParamSpec {
|
||||
const options = Array.from({ length: max - min + 1 }, (_, i) => min + i);
|
||||
return {
|
||||
min,
|
||||
max,
|
||||
step: 1,
|
||||
allowNegative: false,
|
||||
decimal: false,
|
||||
options,
|
||||
};
|
||||
}
|
||||
|
||||
export function getOpacityPercentSpec(current?: number): NumericParamSpec {
|
||||
const options = Array.from({ length: 21 }, (_, i) => i * 5);
|
||||
return {
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
allowNegative: false,
|
||||
decimal: false,
|
||||
options: mergeOptions(0, 100, 5, false, options, 21, current),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user