62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
type ChartPoint = [number, number]
|
|||
|
|
|
||
|
|
/** ضریب بزرگنمایی بصری نوسان — فقط مختصات نمودار؛ tooltip قیمت واقعی را نشان میدهد */
|
||
|
|
const KATOD_CHART_DEVIATION_FACTOR = 3
|
||
|
|
|
||
|
|
/** نمودار boursecu وقتی metal_type = کاتد مس — محور Y فشرده تا نوسان کم هم دیده شود */
|
||
|
|
export function shouldAmplifyKatodMesChart(options: {
|
||
|
|
isBoursecu: boolean
|
||
|
|
metalTypeSetting?: string | number | null
|
||
|
|
}): boolean {
|
||
|
|
if (!options.isBoursecu) {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
const metal = String(options.metalTypeSetting ?? '').trim()
|
||
|
|
return metal === 'کاتد مس'
|
||
|
|
}
|
||
|
|
|
||
|
|
export function computeTightChartYBounds(prices: number[]): { min?: number; max?: number } {
|
||
|
|
const values = prices.filter((value) => Number.isFinite(value) && value > 0)
|
||
|
|
if (values.length < 2) {
|
||
|
|
return {}
|
||
|
|
}
|
||
|
|
|
||
|
|
const dataMin = Math.min(...values)
|
||
|
|
const dataMax = Math.max(...values)
|
||
|
|
const mid = (dataMin + dataMax) / 2
|
||
|
|
let span = dataMax - dataMin
|
||
|
|
|
||
|
|
// حداقل بازه عمودی: ~۰٫۵٪ قیمت میانی (یا ۸۰هزار ریال) تا خط خیلی صاف نباشد
|
||
|
|
const minSpan = Math.max(mid * 0.005, 80_000)
|
||
|
|
if (span < minSpan) {
|
||
|
|
span = minSpan
|
||
|
|
}
|
||
|
|
|
||
|
|
const padding = span * 0.08
|
||
|
|
const center = (dataMin + dataMax) / 2
|
||
|
|
|
||
|
|
return {
|
||
|
|
min: Math.floor(center - span / 2 - padding),
|
||
|
|
max: Math.ceil(center + span / 2 + padding),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** بزرگنمایی انحراف از میانگین — خط نمودار پرتحرکتر میشود بدون تغییر قیمت واقعی در tooltip */
|
||
|
|
export function amplifyChartDeviation(
|
||
|
|
points: ChartPoint[],
|
||
|
|
factor = KATOD_CHART_DEVIATION_FACTOR
|
||
|
|
): ChartPoint[] {
|
||
|
|
if (points.length < 2) {
|
||
|
|
return points
|
||
|
|
}
|
||
|
|
|
||
|
|
const values = points.map((point) => point[1])
|
||
|
|
const mean = values.reduce((sum, value) => sum + value, 0) / values.length
|
||
|
|
|
||
|
|
return points.map(([timestamp, value]) => [
|
||
|
|
timestamp,
|
||
|
|
Math.round(mean + (value - mean) * factor),
|
||
|
|
])
|
||
|
|
}
|