mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-25 23:29:58 -07:00
general: snapshot
This commit is contained in:
@@ -4,11 +4,9 @@ export { averages } from "./consts/averages";
|
||||
|
||||
export function createScaleDatasets<Scale extends ResourceScale>({
|
||||
scale,
|
||||
setActiveResources,
|
||||
groupedKeysToURLPath,
|
||||
}: {
|
||||
scale: Scale;
|
||||
setActiveResources: Setter<Set<ResourceDataset<any, any>>>;
|
||||
groupedKeysToURLPath: GroupedKeysToURLPath[Scale];
|
||||
}) {
|
||||
type Key = keyof typeof groupedKeysToURLPath;
|
||||
@@ -23,7 +21,6 @@ export function createScaleDatasets<Scale extends ResourceScale>({
|
||||
datasets[key as unknown as Exclude<Key, "ohlc">] = createResourceDataset({
|
||||
scale,
|
||||
path: groupedKeysToURLPath[key as Key] as any,
|
||||
setActiveResources,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -31,7 +28,6 @@ export function createScaleDatasets<Scale extends ResourceScale>({
|
||||
const price = createResourceDataset<Scale, OHLC>({
|
||||
scale,
|
||||
path: `/${scale}-to-ohlc`,
|
||||
setActiveResources,
|
||||
});
|
||||
|
||||
Object.assign(datasets, { price });
|
||||
|
||||
@@ -3,10 +3,8 @@ import { createResourceDataset } from "./resource";
|
||||
export { averages } from "./consts/averages";
|
||||
|
||||
export function createDateDatasets({
|
||||
setActiveResources,
|
||||
groupedKeysToURLPath,
|
||||
}: {
|
||||
setActiveResources: Setter<Set<ResourceDataset<any, any>>>;
|
||||
groupedKeysToURLPath: GroupedKeysToURLPath["date"];
|
||||
}) {
|
||||
type Key = keyof typeof groupedKeysToURLPath;
|
||||
@@ -21,7 +19,6 @@ export function createDateDatasets({
|
||||
datasets[key as Exclude<Key, "ohlc">] = createResourceDataset<"date">({
|
||||
scale: "date",
|
||||
path: groupedKeysToURLPath[key as Key],
|
||||
setActiveResources,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -29,7 +26,6 @@ export function createDateDatasets({
|
||||
const price = createResourceDataset<"date", OHLC>({
|
||||
scale: "date",
|
||||
path: "/date-to-ohlc",
|
||||
setActiveResources,
|
||||
});
|
||||
|
||||
Object.assign(datasets, { price });
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { createResourceDataset } from "./resource";
|
||||
|
||||
export function createHeightDatasets({
|
||||
setActiveResources,
|
||||
groupedKeysToURLPath,
|
||||
}: {
|
||||
setActiveResources: Setter<Set<ResourceDataset<any, any>>>;
|
||||
groupedKeysToURLPath: GroupedKeysToURLPath["height"];
|
||||
}) {
|
||||
type Key = keyof typeof groupedKeysToURLPath;
|
||||
@@ -19,7 +17,6 @@ export function createHeightDatasets({
|
||||
datasets[key as Exclude<Key, "ohlc">] = createResourceDataset<"height">({
|
||||
scale: "height",
|
||||
path: groupedKeysToURLPath[key as Key],
|
||||
setActiveResources,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -27,7 +24,6 @@ export function createHeightDatasets({
|
||||
const price = createResourceDataset<"height", OHLC>({
|
||||
scale: "height",
|
||||
path: "/height-to-ohlc",
|
||||
setActiveResources,
|
||||
});
|
||||
|
||||
Object.assign(datasets, { price });
|
||||
|
||||
@@ -7,18 +7,12 @@ export const scales = ["date" as const, "height" as const];
|
||||
|
||||
export const HEIGHT_CHUNK_SIZE = 10_000;
|
||||
|
||||
export function createDatasets({
|
||||
setActiveResources,
|
||||
}: {
|
||||
setActiveResources: Setter<Set<ResourceDataset<any, any>>>;
|
||||
}) {
|
||||
export function createDatasets() {
|
||||
const date = createDateDatasets({
|
||||
setActiveResources,
|
||||
groupedKeysToURLPath: groupedKeysToURLPath.date,
|
||||
});
|
||||
|
||||
const height = createHeightDatasets({
|
||||
setActiveResources,
|
||||
groupedKeysToURLPath: groupedKeysToURLPath.height,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { createLazyMemo } from "@solid-primitives/memo";
|
||||
|
||||
import {
|
||||
ONE_DAY_IN_MS,
|
||||
ONE_HOUR_IN_MS,
|
||||
@@ -8,19 +6,12 @@ import {
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
import { HEIGHT_CHUNK_SIZE } from ".";
|
||||
import { debounce } from "../utils/debounce";
|
||||
|
||||
export function createResourceDataset<
|
||||
Scale extends ResourceScale,
|
||||
Type extends OHLC | number = number,
|
||||
>({
|
||||
scale,
|
||||
path,
|
||||
setActiveResources,
|
||||
}: {
|
||||
scale: Scale;
|
||||
path: string;
|
||||
setActiveResources: Setter<Set<ResourceDataset<any, any>>>;
|
||||
}) {
|
||||
>({ scale, path }: { scale: Scale; path: string }) {
|
||||
type Dataset = Scale extends "date"
|
||||
? FetchedDateDataset<Type>
|
||||
: FetchedHeightDataset<Type>;
|
||||
@@ -85,8 +76,7 @@ export function createResourceDataset<
|
||||
}) as FetchedResult<Scale, Type>[];
|
||||
|
||||
const _fetch = async (id: number) => {
|
||||
const index =
|
||||
scale === "date" ? id - 2009 : Math.floor(id / HEIGHT_CHUNK_SIZE);
|
||||
const index = chunkIdToIndex(scale, id);
|
||||
|
||||
if (
|
||||
index < 0 ||
|
||||
@@ -205,25 +195,43 @@ export function createResourceDataset<
|
||||
fetched.loading = false;
|
||||
};
|
||||
|
||||
const valuesCallback = (vecs: Value[][]) => {
|
||||
let length = 0;
|
||||
for (let i = 0; i < vecs.length; i++) {
|
||||
length += vecs[i].length;
|
||||
}
|
||||
|
||||
if (!length) return;
|
||||
|
||||
const array = new Array(length);
|
||||
let k = 0;
|
||||
for (let i = 0; i < vecs.length; i++) {
|
||||
let vec = vecs[i];
|
||||
for (let j = 0; j < vec.length; j++) {
|
||||
array[k++] = vec[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (k !== length) throw Error("e");
|
||||
|
||||
values.set(array);
|
||||
};
|
||||
|
||||
const debouncedValuesCallback = debounce(valuesCallback, 100);
|
||||
|
||||
const values = createRWS<Value[]>([]);
|
||||
|
||||
createEffect(() => {
|
||||
const vecs = fetchedJSONs.map((fetched) => fetched.vec() || []);
|
||||
debouncedValuesCallback(vecs);
|
||||
});
|
||||
|
||||
const resource: ResourceDataset<Scale, Type> = {
|
||||
scale,
|
||||
url: baseURL,
|
||||
fetch: _fetch,
|
||||
fetchedJSONs,
|
||||
values: createLazyMemo(() => {
|
||||
setActiveResources((resources) => resources.add(resource));
|
||||
|
||||
onCleanup(() =>
|
||||
setActiveResources((resources) => {
|
||||
resources.delete(resource);
|
||||
return resources;
|
||||
}),
|
||||
);
|
||||
|
||||
const flat = fetchedJSONs.flatMap((fetched) => fetched.vec() || []);
|
||||
|
||||
return flat;
|
||||
}),
|
||||
values,
|
||||
drop() {
|
||||
fetchedJSONs.forEach((fetched) => {
|
||||
fetched.at = null;
|
||||
@@ -245,3 +253,7 @@ async function convertResponseToJSON<
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function chunkIdToIndex(scale: ResourceScale, id: number) {
|
||||
return scale === "date" ? id - 2009 : Math.floor(id / HEIGHT_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
15
app/src/scripts/datasets/types.d.ts
vendored
15
app/src/scripts/datasets/types.d.ts
vendored
@@ -8,14 +8,6 @@ type ResourceScale = (typeof import("./index").scales)[index];
|
||||
|
||||
type DatasetValue<T> = T & Numbered & Valued;
|
||||
|
||||
interface Dataset<
|
||||
Scale extends ResourceScale,
|
||||
Value extends SingleValueData | CandlestickData = SingleValueData,
|
||||
> {
|
||||
scale: Scale;
|
||||
values: Accessor<DatasetValue<Value>[]>;
|
||||
}
|
||||
|
||||
interface ResourceDataset<
|
||||
Scale extends ResourceScale,
|
||||
Type extends OHLC | number = number,
|
||||
@@ -27,16 +19,15 @@ interface ResourceDataset<
|
||||
Value extends SingleValueData | CandlestickData = Type extends number
|
||||
? SingleValueData
|
||||
: CandlestickData,
|
||||
> extends Dataset<Scale, Value> {
|
||||
> {
|
||||
scale: Scale;
|
||||
url: string;
|
||||
fetch: (id: number) => void;
|
||||
fetchedJSONs: FetchedResult<Scale, Type>[];
|
||||
values: Accessor<DatasetValue<Value>[]>;
|
||||
drop: VoidFunction;
|
||||
}
|
||||
|
||||
type AnyDataset<Scale extends ResourceScale> = Dataset<Scale> &
|
||||
Partial<ResourceDataset<Scale>>;
|
||||
|
||||
interface FetchedResult<
|
||||
Scale extends ResourceScale,
|
||||
Type extends number | OHLC,
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
import { colors } from "../../utils/colors";
|
||||
import { webSockets } from "../../ws";
|
||||
import { createCandlesticksSeries } from "../series/creators/candlesticks";
|
||||
import { createSeriesLegend } from "../series/creators/legend";
|
||||
import { createLineSeries } from "../series/creators/line";
|
||||
import { initTimeScale } from "./time";
|
||||
|
||||
export const PRICE_SCALE_MOMENTUM_ID = "momentum";
|
||||
|
||||
export const applyPriceSeries = <
|
||||
Scale extends ResourceScale,
|
||||
T extends SingleValueData,
|
||||
>({
|
||||
chart,
|
||||
preset,
|
||||
dataset,
|
||||
seriesType,
|
||||
valuesSkipped,
|
||||
options,
|
||||
activeResources,
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
preset: Preset;
|
||||
valuesSkipped: Accessor<number>;
|
||||
seriesType: Accessor<"Candlestick" | "Line">;
|
||||
activeResources: Accessor<Set<ResourceDataset<any, any>>>;
|
||||
dataset: Dataset<Scale, T>;
|
||||
options?: PriceSeriesOptions;
|
||||
}) => {
|
||||
const id = options?.id || "price";
|
||||
const title = options?.title || "Price";
|
||||
|
||||
const url = "url" in dataset ? (dataset as any).url : undefined;
|
||||
|
||||
const priceScaleOptions: DeepPartialPriceScaleOptions = {
|
||||
mode: 1,
|
||||
...options?.priceScaleOptions,
|
||||
};
|
||||
|
||||
const [ohlcSeries, ohlcColors] = createCandlesticksSeries(chart, options);
|
||||
|
||||
const ohlcLegend = createSeriesLegend({
|
||||
id,
|
||||
presetId: preset.id,
|
||||
title,
|
||||
color: () => ohlcColors,
|
||||
series: ohlcSeries,
|
||||
disabled: () => seriesType() !== "Candlestick",
|
||||
url,
|
||||
});
|
||||
|
||||
ohlcSeries.priceScale().applyOptions(priceScaleOptions);
|
||||
|
||||
// ---
|
||||
|
||||
const lineColor = colors.white;
|
||||
|
||||
const lineSeries = createLineSeries(chart, {
|
||||
color: lineColor,
|
||||
...options?.seriesOptions,
|
||||
});
|
||||
|
||||
const lineLegend = createSeriesLegend({
|
||||
id,
|
||||
presetId: preset.id,
|
||||
title,
|
||||
color: () => lineColor,
|
||||
series: lineSeries,
|
||||
disabled: () => seriesType() !== "Line",
|
||||
visible: ohlcLegend.visible,
|
||||
url,
|
||||
});
|
||||
|
||||
lineSeries.priceScale().applyOptions(priceScaleOptions);
|
||||
|
||||
// ---
|
||||
|
||||
// setMinMaxMarkers({
|
||||
// scale: preset.scale,
|
||||
// candlesticks:
|
||||
// dataset?.values() || datasets[preset.scale].price.values() || ([] as any),
|
||||
// range: chartState.range,
|
||||
// lowerOpacity,
|
||||
// });
|
||||
|
||||
initTimeScale({
|
||||
activeResources,
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
const values = dataset.values();
|
||||
// const values = computeDrawnSeriesValues(dataset.values(), valuesSkipped());
|
||||
|
||||
lineSeries.setData(values);
|
||||
ohlcSeries.setData(values);
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
if (preset.scale === "date") {
|
||||
const latest = webSockets.liveKrakenCandle.latest();
|
||||
|
||||
if (latest) {
|
||||
ohlcSeries.update(latest);
|
||||
lineSeries.update(latest);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { ohlcLegend, lineLegend };
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import { HEIGHT_CHUNK_SIZE } from "../../datasets";
|
||||
import { debounce } from "../../utils/debounce";
|
||||
import { writeURLParam } from "../../utils/urlParams";
|
||||
import { setMinMaxMarkers } from "./markers";
|
||||
import {
|
||||
chartState,
|
||||
LOCAL_STORAGE_RANGE_KEY,
|
||||
@@ -20,9 +19,9 @@ const debouncedUpdateURLParams = debounce((range: TimeRange | null) => {
|
||||
}, 500);
|
||||
|
||||
export function initTimeScale({
|
||||
activeResources,
|
||||
activeDatasets,
|
||||
}: {
|
||||
activeResources: Accessor<Set<ResourceDataset<any, any>>>;
|
||||
activeDatasets: Set<ResourceDataset<any, any>>;
|
||||
}) {
|
||||
setTimeScale(chartState.range);
|
||||
|
||||
@@ -46,7 +45,7 @@ export function initTimeScale({
|
||||
}
|
||||
|
||||
ids.forEach((id) => {
|
||||
activeResources().forEach((resource) => resource.fetch(id));
|
||||
activeDatasets.forEach((dataset) => dataset.fetch(id));
|
||||
});
|
||||
}, 100);
|
||||
|
||||
@@ -63,6 +62,7 @@ export function initTimeScale({
|
||||
chartState.range = range;
|
||||
});
|
||||
}, 50);
|
||||
|
||||
onCleanup(() => clearTimeout(timeout));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,17 +27,16 @@ const whitespaceDateDataset: (SingleValueData & Numbered)[] = new Array(
|
||||
};
|
||||
});
|
||||
|
||||
const whitespaceHeightDataset: (WhitespaceData & Numbered)[] = new Array(
|
||||
840_000,
|
||||
const heightStart = -100_000;
|
||||
const whitespaceHeightDataset: (SingleValueData & Numbered)[] = new Array(
|
||||
1_200_000,
|
||||
)
|
||||
.fill(0)
|
||||
.map(
|
||||
(_, index) =>
|
||||
({
|
||||
time: index,
|
||||
number: index,
|
||||
}) as any,
|
||||
);
|
||||
.map((_, index) => ({
|
||||
time: (heightStart + index) as any,
|
||||
number: heightStart + index,
|
||||
value: NaN,
|
||||
}));
|
||||
|
||||
export function setWhitespace(chart: IChartApi, scale: ResourceScale) {
|
||||
const whitespaceSeries = createLineSeries(chart);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { PRICE_SCALE_MOMENTUM_ID } from "../../chart/price";
|
||||
import { defaultSeriesOptions } from "./options";
|
||||
|
||||
type HistogramOptions = DeepPartial<
|
||||
HistogramStyleOptions & SeriesOptionsCommon
|
||||
>;
|
||||
|
||||
export const PRICE_SCALE_MOMENTUM_ID = "momentum";
|
||||
|
||||
export const createHistogramSeries = (
|
||||
chart: IChartApi,
|
||||
options?: HistogramOptions,
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
import { createChart } from "../lightweightCharts/chart/create";
|
||||
import { applyPriceSeries } from "../lightweightCharts/chart/price";
|
||||
import { chartState } from "../lightweightCharts/chart/state";
|
||||
import { initTimeScale } from "../lightweightCharts/chart/time";
|
||||
import { setWhitespace } from "../lightweightCharts/chart/whitespace";
|
||||
import { createAreaSeries } from "../lightweightCharts/series/creators/area";
|
||||
import {
|
||||
createBaseLineSeries,
|
||||
DEFAULT_BASELINE_COLORS,
|
||||
} from "../lightweightCharts/series/creators/baseLine";
|
||||
import { createCandlesticksSeries } from "../lightweightCharts/series/creators/candlesticks";
|
||||
import { createHistogramSeries } from "../lightweightCharts/series/creators/histogram";
|
||||
import { createSeriesLegend } from "../lightweightCharts/series/creators/legend";
|
||||
import { createLineSeries } from "../lightweightCharts/series/creators/line";
|
||||
import { colors } from "../utils/colors";
|
||||
import { debounce } from "../utils/debounce";
|
||||
import { stringToId } from "../utils/id";
|
||||
import { webSockets } from "../ws";
|
||||
|
||||
export enum SeriesType {
|
||||
Normal,
|
||||
@@ -24,7 +27,7 @@ export enum SeriesType {
|
||||
|
||||
type SeriesConfig<Scale extends ResourceScale> =
|
||||
| {
|
||||
dataset: AnyDataset<Scale>;
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color?: string;
|
||||
colors?: undefined;
|
||||
seriesType: SeriesType.Based;
|
||||
@@ -33,7 +36,7 @@ type SeriesConfig<Scale extends ResourceScale> =
|
||||
defaultVisible?: boolean;
|
||||
}
|
||||
| {
|
||||
dataset: AnyDataset<Scale>;
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color?: string;
|
||||
colors?: string[];
|
||||
seriesType: SeriesType.Histogram;
|
||||
@@ -42,7 +45,7 @@ type SeriesConfig<Scale extends ResourceScale> =
|
||||
defaultVisible?: boolean;
|
||||
}
|
||||
| {
|
||||
dataset: AnyDataset<Scale>;
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color: string;
|
||||
colors?: undefined;
|
||||
seriesType?: SeriesType.Normal | SeriesType.Area;
|
||||
@@ -61,20 +64,18 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
datasets,
|
||||
priceDataset,
|
||||
priceOptions,
|
||||
activeResources,
|
||||
legendSetter,
|
||||
}: {
|
||||
charts: RWS<IChartApi[]>;
|
||||
parentDiv: HTMLDivElement;
|
||||
preset: Preset;
|
||||
legendSetter: Setter<PresetLegend>;
|
||||
priceDataset?: AnyDataset<Scale>;
|
||||
priceDataset?: ResourceDataset<Scale>;
|
||||
priceOptions?: PriceSeriesOptions;
|
||||
priceScaleOptions?: DeepPartialPriceScaleOptions;
|
||||
top?: SeriesConfig<Scale>[];
|
||||
bottom?: SeriesConfig<Scale>[];
|
||||
datasets: Datasets;
|
||||
activeResources: Accessor<Set<ResourceDataset<any, any>>>;
|
||||
}) {
|
||||
reactiveChartList.set((charts) => {
|
||||
charts.forEach((chart) => {
|
||||
@@ -92,7 +93,9 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
|
||||
const priceSeriesType = createRWS<"Candlestick" | "Line">("Candlestick");
|
||||
|
||||
const valuesSkipped = createRWS(0);
|
||||
// const valuesSkipped = createRWS(0);
|
||||
|
||||
const activeDatasets: Set<ResourceDataset<any, any>> = new Set();
|
||||
|
||||
const charts = [top || [], bottom]
|
||||
.flatMap((list) => (list ? [list] : []))
|
||||
@@ -136,17 +139,20 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
const _legendList: PresetLegend = [];
|
||||
|
||||
if (index === 0) {
|
||||
const dataset =
|
||||
priceDataset ||
|
||||
(datasets[preset.scale as Scale].price as unknown as NonNullable<
|
||||
typeof priceDataset
|
||||
>);
|
||||
|
||||
activeDatasets.add(dataset);
|
||||
|
||||
const price = applyPriceSeries({
|
||||
chart,
|
||||
preset,
|
||||
seriesType: priceSeriesType,
|
||||
valuesSkipped,
|
||||
dataset:
|
||||
priceDataset ||
|
||||
(datasets[preset.scale as Scale].price as unknown as NonNullable<
|
||||
typeof priceDataset
|
||||
>),
|
||||
activeResources,
|
||||
// valuesSkipped,
|
||||
dataset,
|
||||
options: priceOptions,
|
||||
});
|
||||
|
||||
@@ -168,6 +174,8 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
options,
|
||||
defaultVisible,
|
||||
}) => {
|
||||
activeDatasets.add(dataset);
|
||||
|
||||
let series: ISeriesApi<
|
||||
"Baseline" | "Line" | "Area" | "Histogram"
|
||||
>;
|
||||
@@ -216,10 +224,10 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
series.setData(
|
||||
dataset?.values() || [],
|
||||
// computeDrawnSeriesValues(dataset?.values(), valuesSkipped()),
|
||||
);
|
||||
const values = dataset.values();
|
||||
console.log(values.length);
|
||||
|
||||
series.setData(values);
|
||||
});
|
||||
|
||||
return series;
|
||||
@@ -275,11 +283,13 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
const ratio = (range.to - range.from) / width;
|
||||
|
||||
if (ratio <= 0.5) {
|
||||
// valuesSkipped.set(0);
|
||||
|
||||
priceSeriesType.set("Candlestick");
|
||||
} else {
|
||||
priceSeriesType.set("Line");
|
||||
|
||||
valuesSkipped.set(Math.floor(ratio / 5));
|
||||
// valuesSkipped.set(Math.floor(ratio / 1.25));
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
@@ -289,6 +299,10 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
50,
|
||||
);
|
||||
|
||||
initTimeScale({
|
||||
activeDatasets,
|
||||
});
|
||||
|
||||
charts.forEach(({ chart }, index) => {
|
||||
chart.timeScale().subscribeVisibleLogicalRangeChange((timeRange) => {
|
||||
// Last chart otherwise length of timescale is Infinity
|
||||
@@ -327,31 +341,270 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
reactiveChartList.set(() => charts.map(({ chart }) => chart));
|
||||
}
|
||||
|
||||
export function computeDrawnSeriesValues<T>(
|
||||
values: DatasetValue<T>[] | undefined,
|
||||
valuesSkipped: number,
|
||||
) {
|
||||
values = values || [];
|
||||
function applyPriceSeries<
|
||||
Scale extends ResourceScale,
|
||||
T extends OHLC | number,
|
||||
>({
|
||||
chart,
|
||||
preset,
|
||||
dataset,
|
||||
seriesType,
|
||||
// valuesSkipped,
|
||||
options,
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
preset: Preset;
|
||||
// valuesSkipped: Accessor<number>;
|
||||
seriesType: Accessor<"Candlestick" | "Line">;
|
||||
dataset: ResourceDataset<Scale, T>;
|
||||
options?: PriceSeriesOptions;
|
||||
}) {
|
||||
// console.time("series add");
|
||||
|
||||
if (valuesSkipped === 0) {
|
||||
return values;
|
||||
} else {
|
||||
const valuesSkippedPlus1 = valuesSkipped + 1;
|
||||
const id = options?.id || "price";
|
||||
const title = options?.title || "Price";
|
||||
|
||||
// console.log(_valuesSkippedPlus1);
|
||||
const url = "url" in dataset ? (dataset as any).url : undefined;
|
||||
|
||||
let length = Math.floor(values.length / valuesSkippedPlus1);
|
||||
const priceScaleOptions: DeepPartialPriceScaleOptions = {
|
||||
mode: 1,
|
||||
...options?.priceScaleOptions,
|
||||
};
|
||||
|
||||
// console.log(length);
|
||||
let [ohlcSeries, ohlcColors] = createCandlesticksSeries(chart, options);
|
||||
|
||||
const filteredValues = new Array(length);
|
||||
const ohlcLegend = createSeriesLegend({
|
||||
id,
|
||||
presetId: preset.id,
|
||||
title,
|
||||
color: () => ohlcColors,
|
||||
series: ohlcSeries,
|
||||
disabled: () => seriesType() !== "Candlestick",
|
||||
url,
|
||||
});
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
filteredValues[i] = values[i * valuesSkippedPlus1];
|
||||
ohlcSeries.priceScale().applyOptions(priceScaleOptions);
|
||||
|
||||
// ---
|
||||
|
||||
const lineColor = colors.white;
|
||||
|
||||
let lineSeries = createLineSeries(chart, {
|
||||
color: lineColor,
|
||||
...options?.seriesOptions,
|
||||
});
|
||||
|
||||
const lineLegend = createSeriesLegend({
|
||||
id,
|
||||
presetId: preset.id,
|
||||
title,
|
||||
color: () => lineColor,
|
||||
series: lineSeries,
|
||||
disabled: () => seriesType() !== "Line",
|
||||
visible: ohlcLegend.visible,
|
||||
url,
|
||||
});
|
||||
|
||||
lineSeries.priceScale().applyOptions(priceScaleOptions);
|
||||
|
||||
// console.timeEnd("series add");
|
||||
|
||||
// lineSeries.setData(whitespaceHeightDataset);
|
||||
// ohlcSeries.setData({ time: 0, value: NaN });
|
||||
|
||||
// ---
|
||||
|
||||
// setMinMaxMarkers({
|
||||
// scale: preset.scale,
|
||||
// candlesticks:
|
||||
// dataset?.values() || datasets[preset.scale].price.values() || ([] as any),
|
||||
// range: chartState.range,
|
||||
// lowerOpacity,
|
||||
// });
|
||||
|
||||
// const startingValue = {
|
||||
// number: -1,
|
||||
// time: -1,
|
||||
// open: NaN,
|
||||
// high: NaN,
|
||||
// low: NaN,
|
||||
// close: NaN,
|
||||
// value: NaN,
|
||||
// };
|
||||
// lineSeries.update(startingValue);
|
||||
// ohlcSeries.update(startingValue);
|
||||
|
||||
// const callback = (
|
||||
// chunks: any[],
|
||||
// valuesSkippedPlus1: number,
|
||||
// length: number,
|
||||
// ) => {
|
||||
// console.time("t");
|
||||
// console.time("a");
|
||||
// // chart.removeSeries(ohlcSeries);
|
||||
// // chart.removeSeries(lineSeries);
|
||||
|
||||
// // ohlcSeries = createCandlesticksSeries(chart, options)[0];
|
||||
|
||||
// // ohlcSeries.priceScale().applyOptions(priceScaleOptions);
|
||||
|
||||
// // lineSeries = createLineSeries(chart, {
|
||||
// // color: lineColor,
|
||||
// // ...options?.seriesOptions,
|
||||
// // });
|
||||
|
||||
// // lineSeries.priceScale().applyOptions(priceScaleOptions);
|
||||
|
||||
// const values = new Array(length);
|
||||
|
||||
// let i = 0;
|
||||
// for (let k = 0; k < chunks.length; k++) {
|
||||
// const chunk = chunks[k];
|
||||
// // const chunk =
|
||||
// // fetchedJSONs[chunkIdToIndex(dataset.scale, activeRange[k])]?.vec?.() ||
|
||||
// // [];
|
||||
|
||||
// for (let j = 0; j < chunk.length; j += valuesSkippedPlus1) {
|
||||
// values[i++] = chunk[j];
|
||||
// // console.log(chunk[j]);
|
||||
// // callback(chunk[j]);
|
||||
// // for (let i = 0; i < seriesList.length; i++) {
|
||||
// // seriesList[i].update(chunk[j]);
|
||||
// // }
|
||||
// // const value = chunk[j];
|
||||
// // console.log(value.time);
|
||||
// // lineSeries.update(value);
|
||||
// // ohlcSeries.update(value);
|
||||
|
||||
// // i++;
|
||||
// }
|
||||
// }
|
||||
|
||||
// console.log(values.length);
|
||||
// console.timeEnd("t");
|
||||
|
||||
// lineSeries.setData(values);
|
||||
|
||||
// console.timeEnd("a");
|
||||
// };
|
||||
|
||||
// const debouncedCallback = debounce(callback, 200);
|
||||
|
||||
createEffect(() => {
|
||||
const values = dataset.values();
|
||||
console.log(values.length);
|
||||
lineSeries.setData(values);
|
||||
ohlcSeries.setData(values);
|
||||
});
|
||||
// createEffect(() =>
|
||||
// computeDrawnSeriesValues(
|
||||
// dataset,
|
||||
// valuesSkipped(),
|
||||
// debouncedCallback,
|
||||
// // [lineSeries, ohlcSeries],
|
||||
// // (value) => {
|
||||
// // try {
|
||||
// // console.log(value);
|
||||
// // lineSeries.update(value);
|
||||
// // ohlcSeries.update(value);
|
||||
// // } catch {}
|
||||
// // }),
|
||||
// ),
|
||||
// );
|
||||
|
||||
createEffect(() => {
|
||||
if (preset.scale === "date") {
|
||||
const latest = webSockets.liveKrakenCandle.latest();
|
||||
|
||||
if (latest) {
|
||||
ohlcSeries.update(latest);
|
||||
lineSeries.update(latest);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// console.log(filteredValues.length);
|
||||
|
||||
return filteredValues;
|
||||
}
|
||||
return { ohlcLegend, lineLegend };
|
||||
}
|
||||
|
||||
// // const computeDrawnSeriesValues = debounce(_computeDrawnSeriesValues, 100);
|
||||
|
||||
// function computeDrawnSeriesValues<
|
||||
// S extends ResourceScale,
|
||||
// T extends OHLC | number,
|
||||
// >(
|
||||
// dataset: ResourceDataset<S, T>,
|
||||
// valuesSkipped: number,
|
||||
// callback: (chunks: any, v: number, l: number) => void,
|
||||
// // seriesList: ISeriesApi<any>[],
|
||||
// ) {
|
||||
// // console.time(dataset.url);
|
||||
|
||||
// const { fetchedJSONs, activeRange: _activeRange } = dataset;
|
||||
|
||||
// const activeRange = _activeRange();
|
||||
|
||||
// const valuesSkippedPlus1 = valuesSkipped + 1;
|
||||
|
||||
// if (valuesSkippedPlus1 === 1) {
|
||||
// console.log("todo valuesSkippedPlus1===1, skip for now");
|
||||
// }
|
||||
|
||||
// // for (let i = 0; i < seriesList.length; i++) {
|
||||
// // seriesList[i].
|
||||
// // }
|
||||
|
||||
// const chunks = new Array(activeRange.length);
|
||||
// let length = 0;
|
||||
|
||||
// for (let i = 0; i < chunks.length; i++) {
|
||||
// const chunk =
|
||||
// fetchedJSONs[chunkIdToIndex(dataset.scale, activeRange[i])]?.vec?.() ||
|
||||
// [];
|
||||
|
||||
// chunks[i] = chunk;
|
||||
|
||||
// length += Math.ceil(chunk.length / valuesSkippedPlus1);
|
||||
// }
|
||||
|
||||
// callback(chunks, valuesSkippedPlus1, length);
|
||||
|
||||
// // setValues(chunks, valuesSkippedPlus1, length, callback);
|
||||
// // }
|
||||
|
||||
// // // const debouncedSetValues = debounce(setValues, 50);
|
||||
// // function setValues(
|
||||
// // chunks: any[],
|
||||
// // valuesSkippedPlus1: number,
|
||||
// // length: number,
|
||||
// // callback: (values: any[]) => void,
|
||||
// // ) {
|
||||
// // const values = new Array(length);
|
||||
|
||||
// // let i = 0;
|
||||
// // for (let k = 0; k < activeRange.length; k++) {
|
||||
// // const chunk = chunks[k];
|
||||
// // // const chunk =
|
||||
// // // fetchedJSONs[chunkIdToIndex(dataset.scale, activeRange[k])]?.vec?.() ||
|
||||
// // // [];
|
||||
|
||||
// // for (let j = 0; j < chunk.length; j += valuesSkippedPlus1) {
|
||||
// // // values[i++] = chunk[j];
|
||||
// // // console.log(chunk[j]);
|
||||
// // // callback(chunk[j]);
|
||||
// // for (let i = 0; i < seriesList.length; i++) {
|
||||
// // seriesList[i].update(chunk[j]);
|
||||
// // }
|
||||
|
||||
// // // i++;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // console.log(i);
|
||||
|
||||
// // if (i !== values.length) {
|
||||
// // console.log({ n: i, values });
|
||||
// // throw Error("error");
|
||||
// // }
|
||||
|
||||
// // console.timeEnd(dataset.url);
|
||||
// }
|
||||
|
||||
1
app/src/scripts/presets/types.d.ts
vendored
1
app/src/scripts/presets/types.d.ts
vendored
@@ -24,7 +24,6 @@ type ApplyPreset = (params: {
|
||||
parentDiv: HTMLDivElement;
|
||||
datasets: Datasets;
|
||||
preset: Preset;
|
||||
activeResources: Accessor<Set<ResourceDataset<any, any>>>;
|
||||
legendSetter: Setter<PresetLegend>;
|
||||
}) => void;
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ export const convertCandleToVolumeColor = (
|
||||
|
||||
export const colors = {
|
||||
white,
|
||||
black,
|
||||
darkWhite,
|
||||
gray,
|
||||
lightBitcoin: yellow,
|
||||
|
||||
Reference in New Issue
Block a user