Загрузка данных


import { PriceScaleMode, SeriesType } from 'lightweight-charts';

import { Indicator } from '@core/Indicator';
import { emaIndicator } from '@core/Indicators/ema';
import { macdHist, macdLine, macdOscillatorFastMa, macdOscillatorSlowMa, macdSignal } from '@core/Indicators/macd';
import { smaIndicator } from '@core/Indicators/sma';
import { volume } from '@core/Indicators/volume';
import { SerieData } from '@core/Series/BaseSeries';

import { Candle } from '@lib';
import { IndicatorsIds } from '@src/constants';
import { INDICATOR_COLOR_PALETTE_MIDDLE_INDEX } from '@src/theme';
import { t } from '@src/translations';
import { Direction, IndicatorConfig, LineCandle, SettingsValues } from '@src/types';

export type ChartTypeToCandleData = {
  ['Bar']: Candle;
  ['Candlestick']: Candle;
  ['Area']: LineCandle;
  ['Baseline']: LineCandle;
  ['Line']: LineCandle;
  ['Histogram']: LineCandle;
  ['Custom']: Candle;
};

export interface IndicatorDataFormatter<T extends SeriesType> {
  mainSeriesData: SerieData[];
  selfData: ChartTypeToCandleData[T][];
  candle?: SerieData;
  indicatorReference?: Indicator;
  settings?: SettingsValues;
}

export const indicatorsMap = (): Partial<Record<IndicatorsIds, IndicatorConfig>> => ({
  [IndicatorsIds.Volume]: {
    series: [
      {
        name: 'Histogram',
        id: 'volume',
        priceScaleOptions: {
          scaleMargins: { top: 0.7, bottom: 0 },
        },
        seriesOptions: {
          priceScaleId: 'vol',
          lastValueVisible: false,
          priceLineVisible: false,
          priceFormat: {
            type: 'volume',
          },
        },
        dataFormatter: (params) => volume(params as IndicatorDataFormatter<'Histogram'>),
      },
    ],
  },
  [IndicatorsIds.SMA]: {
    series: [
      {
        name: 'Line', // todo: change with enum
        id: 'sma',
        seriesOptions: {},
        dataFormatter: (params) => smaIndicator(params as IndicatorDataFormatter<'Line'>),
      },
    ],
    settings: [
      { type: 'number', key: 'length', label: t('Length'), defaultValue: 10, min: 1, max: 500 },
      {
        type: 'select',
        key: 'source',
        label: t('Data'),
        defaultValue: 'close',
        options: [
          { label: t('Open price'), value: 'open' },
          { label: t('Max'), value: 'high' },
          { label: t('Min'), value: 'low' },
          { label: t('Close price'), value: 'close' },
        ],
      },
      { type: 'number', key: 'offset', label: t('Offset'), defaultValue: 0, min: -100, max: 100 },
    ],
  },
  [IndicatorsIds.EMA]: {
    paletteStartIndex: INDICATOR_COLOR_PALETTE_MIDDLE_INDEX,
    series: [
      {
        name: 'Line', // todo: change with enum
        id: 'ema',
        seriesOptions: {},
        dataFormatter: (params) => {
          return emaIndicator(params as IndicatorDataFormatter<'Line'>);
        },
      },
    ],
    settings: [
      { type: 'number', key: 'length', label: t('Length'), defaultValue: 10, min: 1, max: 500 },
      {
        type: 'select',
        key: 'source',
        label: t('Data'),
        defaultValue: 'close',
        options: [
          { label: t('Open price'), value: 'open' },
          { label: t('Max'), value: 'high' },
          { label: t('Min'), value: 'low' },
          { label: t('Close price'), value: 'close' },
        ],
      },
      { type: 'number', key: 'offset', label: t('Offset'), defaultValue: 0, min: -100, max: 100 },
    ],
  },

  [IndicatorsIds.MACD]: {
    newPane: true,
    series: [
      {
        name: 'Line', // todo: change with enum
        id: 'oscillatorSlowMa',
        dataFormatter: (params) => macdOscillatorSlowMa(params as IndicatorDataFormatter<'Line'>),
        seriesOptions: {
          priceScaleId: 'macd_oscillator_ma',
          visible: false,
          lastValueVisible: false,
        },
      },
      {
        name: 'Line', // todo: change with enum
        id: 'oscillatorFastMa',
        dataFormatter: (params) => macdOscillatorFastMa(params as IndicatorDataFormatter<'Line'>),
        seriesOptions: {
          priceScaleId: 'macd_oscillator_ma',
          visible: false,
          lastValueVisible: false,
        },
      },
      {
        name: 'Line', // todo: change with enum
        id: 'macdLine',
        actLikeMainSerie: true,
        priceScaleOptions: {
          mode: PriceScaleMode.Normal,
        },
        dataFormatter: (params) => macdLine(params as IndicatorDataFormatter<'Line'>),
        seriesOptions: {
          priceScaleId: Direction.Right,
          lastValueVisible: false,
        },
      },
      {
        name: 'Line', // todo: change with enum
        actLikeMainSerie: true,
        id: 'signalLine',
        priceScaleOptions: {
          mode: PriceScaleMode.Normal,
        },
        dataFormatter: (params) => macdSignal(params as IndicatorDataFormatter<'Line'>),
        seriesOptions: {
          priceScaleId: Direction.Right,
          lastValueVisible: false,
        },
      },
      {
        name: 'Histogram', // todo: change with enum
        actLikeMainSerie: true,
        id: 'histogram',
        priceScaleOptions: {
          autoScale: true,
        },
        seriesOptions: {
          priceScaleId: Direction.Right,
          lastValueVisible: false,
        },
        dataFormatter: (params) => macdHist(params as IndicatorDataFormatter<'Histogram'>),
      },
    ],
    settings: [
      {
        type: 'select',
        key: 'source',
        label: t('Data'),
        defaultValue: 'close',
        options: [
          { label: t('Open price'), value: 'open' },
          { label: t('Max'), value: 'high' },
          { label: t('Min'), value: 'low' },
          { label: t('Close price'), value: 'close' },
        ],
      },
      { type: 'number', key: 'fastLength', label: t('Fast length'), defaultValue: 12, min: 1, max: 500 },
      { type: 'number', key: 'slowLength', label: t('Slow length'), defaultValue: 26, min: 1, max: 500 },
      { type: 'number', key: 'signalLength', label: t('Signal length'), defaultValue: 9, min: 1, max: 500 },
      {
        type: 'select',
        key: 'oscillatorMaType',
        label: t('Oscillator MA type'),
        defaultValue: 'ema',
        options: [
          { label: 'EMA', value: 'ema' },
          { label: 'SMA', value: 'sma' },
        ],
      },
      {
        type: 'select',
        key: 'signalMaType',
        label: t('Signal MA type'),
        defaultValue: 'ema',
        options: [
          { label: 'EMA', value: 'ema' },
          { label: 'SMA', value: 'sma' },
        ],
      },
    ],
  },
});


import { DrawingsManagerSnapshot } from '@core/DrawingsManager';
import { ChartSeriesType, DateFormat, IndicatorsIds, Intervals, Timeframes } from '@lib';
import { Direction } from '@src/types/chart';
import { SymbolInfo, SymbolInfoInput } from '@src/types/symbol';
import { TimeFormat } from '@src/types/timeScale';

import { SettingsValues } from './settings';

import type { PriceScaleMode } from 'lightweight-charts';

export type PriceScaleSide = Direction.Left | Direction.Right;

export interface ISerializable<T extends object> {
  getSnapshot: () => T;
}

export interface InitialSnapshot extends SymbolInfoInput {
  timeframe: Timeframes; // todo: move to snap
  chartSeriesType: ChartSeriesType; // todo: move to snap
}

export interface MoexChartSnapshotInput {
  // settings: ChartSettingsSnapshot;
  charts: ChartSnapshotInput[];
}

export interface MoexChartSnapshot {
  // settings: ChartSettingsSnapshot;
  charts: ChartSnapshot[];
}

interface ChartSnapshotBase {
  timeframe: Timeframes;
  chartSeriesType: ChartSeriesType;
  timeFormat?: TimeFormat;
  dateFormat?: DateFormat;
  interval?: Intervals | null;
  panes: PaneSnapshot[];
}

export interface ChartSnapshotInput extends ChartSnapshotBase, SymbolInfoInput {}
export interface ChartSnapshot extends ChartSnapshotBase, SymbolInfo {}

export interface PriceScaleSnapshot {
  side: PriceScaleSide;
  mode: PriceScaleMode;
}

export interface PaneSnapshot {
  isMain: boolean;
  id: number;
  indicators: (IndicatorSnapshot | CompareSnapshot)[];
  drawings: DrawingsManagerSnapshot;
  priceScales?: PriceScaleSnapshot[];
}

export interface CompareSnapshot extends Partial<DOMObjectSnapshot> {
  symbolInfo: SymbolInfoInput;
  seriesName: ChartSeriesType;
  scale: Direction;
}

export interface IndicatorSnapshot extends Partial<DOMObjectSnapshot> {
  indicatorType: IndicatorsIds;
  settings?: SettingsValues;
}

// todo: move DrawingsManagerSnapshot here

export interface DOMObjectSnapshot {
  id: string;
  name: string;
  zIndex: number;
  hidden: boolean;
  paneId: number;
}