mirror of
https://github.com/freqtrade/frequi.git
synced 2024-11-10 10:21:55 +00:00
pct tool draft
This commit is contained in:
parent
722a279578
commit
635d70fe56
10
src/auto-imports.d.ts
vendored
10
src/auto-imports.d.ts
vendored
|
@ -8,6 +8,7 @@ declare global {
|
|||
const ColorPreferences: typeof import('./stores/colors')['ColorPreferences']
|
||||
const DashboardLayout: typeof import('./stores/layout')['DashboardLayout']
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const KeyCode: typeof import('./composables/inputListener')['KeyCode']
|
||||
const OpenTradeVizOptions: typeof import('./stores/settings')['OpenTradeVizOptions']
|
||||
const TradeLayout: typeof import('./stores/layout')['TradeLayout']
|
||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
||||
|
@ -186,6 +187,7 @@ declare global {
|
|||
const useIdle: typeof import('@vueuse/core')['useIdle']
|
||||
const useImage: typeof import('@vueuse/core')['useImage']
|
||||
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
|
||||
const useInputListener: typeof import('./composables/inputListener')['useInputListener']
|
||||
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
|
||||
const useInterval: typeof import('@vueuse/core')['useInterval']
|
||||
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
|
||||
|
@ -215,6 +217,7 @@ declare global {
|
|||
const usePairlistConfigStore: typeof import('./stores/pairlistConfig')['usePairlistConfigStore']
|
||||
const useParallax: typeof import('@vueuse/core')['useParallax']
|
||||
const useParentElement: typeof import('@vueuse/core')['useParentElement']
|
||||
const usePercentageTool: typeof import('./composables/percentageTool')['usePercentageTool']
|
||||
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
|
||||
const usePermission: typeof import('@vueuse/core')['usePermission']
|
||||
const usePlotConfigStore: typeof import('./stores/plotConfig')['usePlotConfigStore']
|
||||
|
@ -302,6 +305,7 @@ declare global {
|
|||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
// for vue template auto import
|
||||
import { UnwrapRef } from 'vue'
|
||||
|
@ -310,6 +314,7 @@ declare module 'vue' {
|
|||
readonly ColorPreferences: UnwrapRef<typeof import('./stores/colors')['ColorPreferences']>
|
||||
readonly DashboardLayout: UnwrapRef<typeof import('./stores/layout')['DashboardLayout']>
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly KeyCode: UnwrapRef<typeof import('./composables/inputListener')['KeyCode']>
|
||||
readonly OpenTradeVizOptions: UnwrapRef<typeof import('./stores/settings')['OpenTradeVizOptions']>
|
||||
readonly TradeLayout: UnwrapRef<typeof import('./stores/layout')['TradeLayout']>
|
||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||
|
@ -488,6 +493,7 @@ declare module 'vue' {
|
|||
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
|
||||
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
|
||||
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
|
||||
readonly useInputListener: UnwrapRef<typeof import('./composables/inputListener')['useInputListener']>
|
||||
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
|
||||
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
|
||||
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
|
||||
|
@ -517,6 +523,7 @@ declare module 'vue' {
|
|||
readonly usePairlistConfigStore: UnwrapRef<typeof import('./stores/pairlistConfig')['usePairlistConfigStore']>
|
||||
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
|
||||
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
|
||||
readonly usePercentageTool: UnwrapRef<typeof import('./composables/percentageTool')['usePercentageTool']>
|
||||
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
|
||||
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
|
||||
readonly usePlotConfigStore: UnwrapRef<typeof import('./stores/plotConfig')['usePlotConfigStore']>
|
||||
|
@ -606,6 +613,7 @@ declare module '@vue/runtime-core' {
|
|||
readonly ColorPreferences: UnwrapRef<typeof import('./stores/colors')['ColorPreferences']>
|
||||
readonly DashboardLayout: UnwrapRef<typeof import('./stores/layout')['DashboardLayout']>
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly KeyCode: UnwrapRef<typeof import('./composables/inputListener')['KeyCode']>
|
||||
readonly OpenTradeVizOptions: UnwrapRef<typeof import('./stores/settings')['OpenTradeVizOptions']>
|
||||
readonly TradeLayout: UnwrapRef<typeof import('./stores/layout')['TradeLayout']>
|
||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||
|
@ -784,6 +792,7 @@ declare module '@vue/runtime-core' {
|
|||
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
|
||||
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
|
||||
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
|
||||
readonly useInputListener: UnwrapRef<typeof import('./composables/inputListener')['useInputListener']>
|
||||
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
|
||||
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
|
||||
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
|
||||
|
@ -813,6 +822,7 @@ declare module '@vue/runtime-core' {
|
|||
readonly usePairlistConfigStore: UnwrapRef<typeof import('./stores/pairlistConfig')['usePairlistConfigStore']>
|
||||
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
|
||||
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
|
||||
readonly usePercentageTool: UnwrapRef<typeof import('./composables/percentageTool')['usePercentageTool']>
|
||||
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
|
||||
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
|
||||
readonly usePlotConfigStore: UnwrapRef<typeof import('./stores/plotConfig')['usePlotConfigStore']>
|
||||
|
|
|
@ -133,6 +133,8 @@ const diffCols = computed(() => {
|
|||
return getDiffColumnsFromPlotConfig(props.plotConfig);
|
||||
});
|
||||
|
||||
usePercentageTool(candleChart);
|
||||
|
||||
function updateChart(initial = false) {
|
||||
if (!hasData.value) {
|
||||
return;
|
||||
|
|
30
src/composables/inputListener.ts
Normal file
30
src/composables/inputListener.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
// codes we care about
|
||||
export enum KeyCode {
|
||||
SHIFT_LEFT = 'ShiftLeft',
|
||||
CTRL_LEFT = 'ControlLeft',
|
||||
}
|
||||
|
||||
export function useInputListener() {
|
||||
const allCodes = Object.values(KeyCode) as string[];
|
||||
const pressed = ref<string[]>([]);
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
if (!allCodes.includes(e.code) || pressed.value.includes(e.code)) return;
|
||||
pressed.value.push(e.code);
|
||||
}
|
||||
|
||||
function onKeyUp(e: KeyboardEvent) {
|
||||
const i = pressed.value.indexOf(e.code);
|
||||
if (i > -1) {
|
||||
pressed.value.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
useEventListener(document, 'keydown', onKeyDown);
|
||||
useEventListener(document, 'keyup', onKeyUp);
|
||||
|
||||
return {
|
||||
isKeyPressed: (key: KeyCode) => pressed.value.includes(key),
|
||||
isAnyPressed: computed(() => pressed.value.length > 0),
|
||||
};
|
||||
}
|
106
src/composables/percentageTool.ts
Normal file
106
src/composables/percentageTool.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
import { use } from 'echarts/core';
|
||||
import { ElementEvent } from 'echarts';
|
||||
import { useInputListener } from './inputListener';
|
||||
import { GraphicComponent } from 'echarts/components';
|
||||
|
||||
use([GraphicComponent]);
|
||||
|
||||
export function usePercentageTool(chartRef: Ref) {
|
||||
const inputListener = useInputListener();
|
||||
|
||||
const mousePos = ref({ x: 0, y: 0 });
|
||||
const startPos = ref({ x: 0, y: 0 });
|
||||
const drawLimitPerSecond = 144;
|
||||
const canDraw = ref(true);
|
||||
const active = ref(false);
|
||||
|
||||
function mouseMove(e: ElementEvent) {
|
||||
mousePos.value.x = e.offsetX;
|
||||
mousePos.value.y = e.offsetY;
|
||||
|
||||
if (!active.value || !canDraw.value) return;
|
||||
draw(e.offsetX, e.offsetY);
|
||||
}
|
||||
|
||||
function drawStart() {
|
||||
active.value = true;
|
||||
startPos.value = { ...mousePos.value };
|
||||
chartRef.value?.setOption({
|
||||
dataZoom: [{ disabled: true }],
|
||||
graphic: [
|
||||
{
|
||||
type: 'line',
|
||||
shape: {
|
||||
x1: mousePos.value.x,
|
||||
x2: mousePos.value.x,
|
||||
y1: mousePos.value.y,
|
||||
y2: mousePos.value.y,
|
||||
},
|
||||
style: {
|
||||
stroke: 'white',
|
||||
},
|
||||
},
|
||||
{ type: 'text', z: 5 },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function drawEnd() {
|
||||
active.value = false;
|
||||
chartRef.value?.setOption({
|
||||
dataZoom: [{ disabled: false }],
|
||||
graphic: [{ $action: 'remove' }, { $action: 'remove' }],
|
||||
});
|
||||
}
|
||||
|
||||
function draw(x: number, y: number) {
|
||||
const startPrice = Number(
|
||||
chartRef.value?.convertFromPixel({ seriesIndex: 0 }, [startPos.value.x, startPos.value.y])[1],
|
||||
);
|
||||
const endPrice = Number(chartRef.value?.convertFromPixel({ seriesIndex: 0 }, [x, y])[1]);
|
||||
const pct = Math.abs(((startPrice - endPrice) / startPrice) * 100).toFixed(2);
|
||||
|
||||
chartRef.value?.setOption({
|
||||
graphic: [
|
||||
{
|
||||
shape: {
|
||||
x2: x,
|
||||
y2: y,
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
x: x,
|
||||
y: y - 20,
|
||||
text: (startPrice < endPrice ? pct : '-' + pct) + '%',
|
||||
font: '16px sans-serif',
|
||||
fill: 'white',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
canDraw.value = false;
|
||||
setTimeout(() => {
|
||||
canDraw.value = true;
|
||||
}, 1000 / drawLimitPerSecond);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => inputListener.isAnyPressed.value,
|
||||
() => {
|
||||
if (inputListener.isKeyPressed(KeyCode.SHIFT_LEFT)) {
|
||||
drawStart();
|
||||
} else if (active.value) {
|
||||
drawEnd();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
chartRef.value?.chart.getZr().on('mousemove', mouseMove);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
chartRef.value?.chart.getZr().off('mousemove', mouseMove);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user