st-comp 0.0.167 → 0.0.169
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/KlinePlus.cjs +4 -4
- package/es/KlinePlus.js +543 -483
- package/es/style.css +1 -1
- package/lib/bundle.js +1 -1
- package/lib/bundle.umd.cjs +182 -182
- package/lib/{index-6c539dc9.js → index-832c69a2.js} +13975 -13915
- package/lib/{python-b2c12764.js → python-bfb3b4c6.js} +1 -1
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/packages/KlinePlus/index.vue +59 -9
- package/packages/KlinePlus/utils.js +41 -1
- package/src/pages/KlinePlus/index.vue +25 -6
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import dayjs from "dayjs";
|
|
|
4
4
|
import * as echarts from "echarts";
|
|
5
5
|
import { stMath, debounce, addResizeListener } from "st-func";
|
|
6
6
|
import { ref, watch, computed, onMounted, onUnmounted, inject } from "vue";
|
|
7
|
-
import { loadKlineConfig, getSubOptions, mergeklineData, handleMarkPointTradeLog, handleNetPositionLine, handleMarkPointOffset, normalizeToKlineTimeByMatch } from "./utils.js";
|
|
7
|
+
import { loadKlineConfig, checkTimeInterval, getSubOptions, mergeklineData, handleMarkPointTradeLog, handleNetPositionLine, handleMarkPointOffset, normalizeToKlineTimeByMatch } from "./utils.js";
|
|
8
8
|
import Tips from "./components/Tips.vue";
|
|
9
9
|
import SliderChart from "./components/SliderChart.vue";
|
|
10
10
|
|
|
@@ -174,16 +174,47 @@ const getMainData = async ({ startTime, endTime }) => {
|
|
|
174
174
|
contractType: props.varietyStock ? null : props.klineType, // 合约类型
|
|
175
175
|
mainIndicatorList: props.indicatorStore.getIndicatorParams(props.mainIndicator),
|
|
176
176
|
subIndicator: subIndicator.value,
|
|
177
|
-
startTime: dayjs(startTime).subtract(50, "day").format("YYYY-MM-DD HH:mm:ss"), // 确保缩放, 多请求部分数据, 也可以兼容undefined的情况
|
|
178
|
-
endTime: dayjs(endTime).add(50, "day").format("YYYY-MM-DD HH:mm:ss"), // 确保缩放, 多请求部分数据, 也可以兼容undefined的情况
|
|
179
177
|
deleteFirstNumber: 1, // >> 重要: 绩效后端特殊要求传参 <<
|
|
180
178
|
};
|
|
179
|
+
// Echarts如果一屏如果正好展示了所有数据, 是无法缩放触发加载更多的
|
|
180
|
+
// 所以在请求中需要对开始和结束时间进行延伸, 但是首屏的展示时间定位还是会以传入的开始结束时间为准
|
|
181
|
+
if (["1", "2", "3", "4", "5"].includes(props.cycle)) {
|
|
182
|
+
Object.assign(params, {
|
|
183
|
+
startTime: dayjs(startTime).subtract(1, "day").format("YYYY-MM-DD HH:mm:ss"),
|
|
184
|
+
endTime: dayjs(endTime).add(1, "day").format("YYYY-MM-DD HH:mm:ss"),
|
|
185
|
+
});
|
|
186
|
+
} else if (["6", "7"].includes(props.cycle)) {
|
|
187
|
+
Object.assign(params, {
|
|
188
|
+
startTime: dayjs(startTime).subtract(50, "day").format("YYYY-MM-DD HH:mm:ss"),
|
|
189
|
+
endTime: dayjs(endTime).add(50, "day").format("YYYY-MM-DD HH:mm:ss"),
|
|
190
|
+
});
|
|
191
|
+
} else {
|
|
192
|
+
Object.assign(params, {
|
|
193
|
+
startTime: dayjs(startTime).subtract(10, "month").format("YYYY-MM-DD HH:mm:ss"),
|
|
194
|
+
endTime: dayjs(endTime).add(10, "month").format("YYYY-MM-DD HH:mm:ss"),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
181
197
|
const { body } = await request.post("/middleLayer/kline/getKline", params);
|
|
182
198
|
klineData.value = body ?? { data: [], mainIndicator: [], subIndicator: [], time: [] };
|
|
183
199
|
|
|
184
|
-
// 绘制图表
|
|
185
|
-
|
|
186
|
-
|
|
200
|
+
// 找到匹配对应传入的开始, 结束时间的数据索引, 绘制图表
|
|
201
|
+
let startValue = -1;
|
|
202
|
+
let endValue = -1;
|
|
203
|
+
for (let index = 0; index < klineData.value.time.length; index++) {
|
|
204
|
+
const day = dayjs(klineData.value.time[index]).format("YYYY-MM-DD");
|
|
205
|
+
if (startValue !== -1 && endValue !== -1) break;
|
|
206
|
+
if (startValue === -1) {
|
|
207
|
+
if (new Date(day) === new Date(startTime)) startValue = index;
|
|
208
|
+
else if (new Date(day) > new Date(startTime)) startValue = index - 1;
|
|
209
|
+
}
|
|
210
|
+
if (endValue === -1) {
|
|
211
|
+
if (new Date(day) === new Date(endTime)) endValue = index;
|
|
212
|
+
else if (new Date(day) > new Date(endTime)) endValue = index - 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (endValue === -1) endValue = klineData.value.time.length - 1;
|
|
216
|
+
// const startValue = klineData.value.time.findIndex((item) => new Date(item) >= new Date(startTime));
|
|
217
|
+
// const endValue = klineData.value.time.findIndex((item) => new Date(item) >= new Date(endTime));
|
|
187
218
|
draw({
|
|
188
219
|
startValue: startValue === -1 ? 0 : startValue,
|
|
189
220
|
endValue: endValue === -1 ? klineData.value.time.length - 1 : endValue,
|
|
@@ -578,7 +609,11 @@ const draw = (params = { startValue: 0, endValue: 0 }) => {
|
|
|
578
609
|
|
|
579
610
|
// 拖拽轴: 拖拽回调
|
|
580
611
|
const handleSliderChange = (params) => {
|
|
581
|
-
const
|
|
612
|
+
const [startTime, endTime] = checkTimeInterval({
|
|
613
|
+
startTime: params.startTime,
|
|
614
|
+
endTime: params.endTime,
|
|
615
|
+
cycle: props.cycle,
|
|
616
|
+
});
|
|
582
617
|
getMainData({ startTime, endTime });
|
|
583
618
|
};
|
|
584
619
|
// 键盘控制 [↑↓←→缩放平移]
|
|
@@ -659,9 +694,24 @@ watch(
|
|
|
659
694
|
},
|
|
660
695
|
{ deep: true }
|
|
661
696
|
);
|
|
662
|
-
// 监控: [
|
|
697
|
+
// 监控: [周期选项] => 重加载K线 (缩放不变+校验时间间隔)
|
|
698
|
+
watch(
|
|
699
|
+
() => [props.cycle],
|
|
700
|
+
() => {
|
|
701
|
+
const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
|
|
702
|
+
const [startTime, endTime] = checkTimeInterval({
|
|
703
|
+
startTime: klineData.value.time[startValue],
|
|
704
|
+
endTime: klineData.value.time[endValue],
|
|
705
|
+
cycle: props.cycle,
|
|
706
|
+
type: "middle",
|
|
707
|
+
});
|
|
708
|
+
getMainData({ startTime, endTime });
|
|
709
|
+
},
|
|
710
|
+
{ deep: true }
|
|
711
|
+
);
|
|
712
|
+
// 监控: [主指标, 副指标, 指标配置, 复权选项, 常用选项] => 重加载K线 (缩放不变)
|
|
663
713
|
watch(
|
|
664
|
-
() => [props.mainIndicator, subIndicator.value, props.indicatorStore?.filterIndicator, props.indicatorStore?.customIndicator, props.
|
|
714
|
+
() => [props.mainIndicator, subIndicator.value, props.indicatorStore?.filterIndicator, props.indicatorStore?.customIndicator, props.rightType, props.klineType],
|
|
665
715
|
() => {
|
|
666
716
|
const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
|
|
667
717
|
const [startTime, endTime] = [klineData.value.time[startValue], klineData.value.time[endValue]];
|
|
@@ -14,6 +14,46 @@ export const loadKlineConfig = {
|
|
|
14
14
|
loadAddCount: 2000,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// 前端估算K线根数的周期分布
|
|
18
|
+
export const dayBarsNumByCycle = {
|
|
19
|
+
1: 240, // 每天240根(4小时×60分钟)
|
|
20
|
+
2: 48, // 每天48根(4小时×12根)
|
|
21
|
+
3: 16, // 每天16根(4小时×4根)
|
|
22
|
+
4: 8, // 每天8根(4小时×2根)
|
|
23
|
+
5: 4, // 每天4根(4小时×1根)
|
|
24
|
+
6: 1, // 每天1根
|
|
25
|
+
7: 0.2, // 每周1根(按5个交易日算)
|
|
26
|
+
8: 0.033, // 每月1根(按21个交易日算)
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @description: 校验时间间隔, 避免开始和结束时间过大, 超过一屏根数上限
|
|
31
|
+
*/
|
|
32
|
+
export const checkTimeInterval = ({ startTime, endTime, cycle, type = "end" }) => {
|
|
33
|
+
// 大切小时可能会出现请求超过一屏上限的数据量, 进行时间间隔校验, 由于是估算, 所以计算时可以比一屏上限根数多一些
|
|
34
|
+
const { maxValueSpan } = loadKlineConfig;
|
|
35
|
+
const N = Math.ceil((maxValueSpan + 1000) / dayBarsNumByCycle[cycle]);
|
|
36
|
+
const d1 = dayjs(startTime);
|
|
37
|
+
const d2 = dayjs(endTime);
|
|
38
|
+
const diff = d2.diff(d1, "day");
|
|
39
|
+
// 未超出间隔, 返回原本的开始, 结束时间
|
|
40
|
+
if (diff <= N) return [startTime, endTime];
|
|
41
|
+
// 超出间隔, 按照期望以结束时间, 还是中间时间去计算
|
|
42
|
+
if (type === "end") return [dayjs(endTime).subtract(N, "day").format("YYYY-MM-DD HH:mm:ss"), endTime];
|
|
43
|
+
if (type === "middle") {
|
|
44
|
+
const middleTime = dayjs((dayjs(startTime).valueOf() + dayjs(endTime).valueOf()) / 2).format("YYYY-MM-DD HH:mm:ss");
|
|
45
|
+
console.log("超过一屏数量上限, 进行中间时间计算", middleTime, N / 2);
|
|
46
|
+
return [
|
|
47
|
+
dayjs(middleTime)
|
|
48
|
+
.subtract(N / 2, "day")
|
|
49
|
+
.format("YYYY-MM-DD HH:mm:ss"),
|
|
50
|
+
dayjs(middleTime)
|
|
51
|
+
.add(N / 2, "day")
|
|
52
|
+
.format("YYYY-MM-DD HH:mm:ss"),
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
17
57
|
// 获取副图配置
|
|
18
58
|
const getSubBarStyle = (data, index) => {
|
|
19
59
|
const itemData = data[index];
|
|
@@ -446,7 +486,7 @@ export const normalizeToKlineTimeByMatch = (klineTimeArray, timeRange, cycle) =>
|
|
|
446
486
|
klineEnd = klineTimeArray.findLast((t) => new Date(t).getTime() <= new Date(end).getTime());
|
|
447
487
|
}
|
|
448
488
|
}
|
|
449
|
-
return [klineStart, klineEnd]
|
|
489
|
+
return [klineStart, klineEnd];
|
|
450
490
|
};
|
|
451
491
|
|
|
452
492
|
// 统一处理markPoint标记点的偏移量
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
<div style="display: flex; align-items: center; gap: 10px">
|
|
4
|
+
<el-button @click="stKlineConfigRef?.open">打开K线自定义配置</el-button>
|
|
5
|
+
<el-select
|
|
6
|
+
v-model="cycle"
|
|
7
|
+
style="width: 100px"
|
|
8
|
+
>
|
|
9
|
+
<el-option
|
|
10
|
+
v-for="item in cycleOptions"
|
|
11
|
+
:key="item.value"
|
|
12
|
+
:value="item.value"
|
|
13
|
+
:label="item.label"
|
|
14
|
+
/>
|
|
15
|
+
</el-select>
|
|
16
|
+
</div>
|
|
9
17
|
<div class="main">
|
|
10
18
|
<template v-if="!loading">
|
|
11
19
|
<st-klinePlus
|
|
@@ -25,6 +33,11 @@
|
|
|
25
33
|
/>
|
|
26
34
|
</template>
|
|
27
35
|
</div>
|
|
36
|
+
<st-klineConfig
|
|
37
|
+
ref="stKlineConfigRef"
|
|
38
|
+
:indicatorStore="indicatorStore"
|
|
39
|
+
@callBack="(formJson) => handleUserKlineConfig('update', formJson)"
|
|
40
|
+
/>
|
|
28
41
|
</div>
|
|
29
42
|
</template>
|
|
30
43
|
|
|
@@ -39,6 +52,12 @@ const loading = ref(true);
|
|
|
39
52
|
const userKlineConfig = reactive({});
|
|
40
53
|
provide("userKlineConfig", userKlineConfig);
|
|
41
54
|
|
|
55
|
+
const cycleOptions = [
|
|
56
|
+
{ label: "1m", value: "1" },
|
|
57
|
+
{ label: "1d", value: "6" },
|
|
58
|
+
{ label: "1mon", value: "8" },
|
|
59
|
+
];
|
|
60
|
+
|
|
42
61
|
const varietyName = ref(null);
|
|
43
62
|
const varietyCode = ref("000016");
|
|
44
63
|
const varietyStock = ref(1); // 0: 期货, 1: 股票, 2: 期权
|