feat(web): K线周期下拉统一共享常量:列全miniQMT成品K线(1m~60m/日/周/月,周月由日线合成),默认日线;模拟盘/实盘/策略实例三表单同源;标注回放数据可用性(d/15m本地有) [nas]
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
// K 线周期选项(全局共享)。
|
||||
// 来源=miniQMT(xtdata)成品K线:订阅时直接指明周期,QMT 端已合成好,无需自己从 tick 拼。
|
||||
// 默认日线;策略/实例可自行改。
|
||||
// replayOk=本地库有该周期历史数据(回放/回测可用,当前 d/15m);
|
||||
// 其余周期影子柜台实时订阅可用,回放待本地补数据。
|
||||
export interface IntervalOption {
|
||||
label: string
|
||||
value: string
|
||||
matchHint?: string
|
||||
replayOk?: boolean
|
||||
}
|
||||
|
||||
export const DEFAULT_INTERVAL = 'd'
|
||||
|
||||
export const INTERVAL_OPTIONS: IntervalOption[] = [
|
||||
{ label: '日线', value: 'd', matchHint: '每日 1 个撮合点', replayOk: true },
|
||||
{ label: '60 分钟', value: '60m' },
|
||||
{ label: '30 分钟', value: '30m' },
|
||||
{ label: '15 分钟', value: '15m', matchHint: '每日约 16 个撮合点(每根 15m K线撮合)', replayOk: true },
|
||||
{ label: '5 分钟', value: '5m' },
|
||||
{ label: '1 分钟', value: '1m' },
|
||||
{ label: '周线', value: 'w', matchHint: '由日线合成' },
|
||||
{ label: '月线', value: 'mon', matchHint: '由日线合成' },
|
||||
]
|
||||
|
||||
export function intervalLabel(v: string): string {
|
||||
return INTERVAL_OPTIONS.find((o) => o.value === v)?.label ?? v
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { createLive, type LiveCreateRequest } from '@/api/live'
|
||||
import { apiClient } from '@/api/client'
|
||||
import { INTERVAL_OPTIONS } from '@/constants/intervals'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -58,7 +59,7 @@ const form = ref<LiveCreateRequest>({
|
||||
size: 100,
|
||||
forbid_short: true,
|
||||
},
|
||||
interval: '15m',
|
||||
interval: 'd',
|
||||
initial_capital: 1_000_000,
|
||||
connect_wait_sec: 10,
|
||||
init_wait_sec: 60,
|
||||
@@ -206,8 +207,13 @@ async function onSubmit(): Promise<void> {
|
||||
<span class="muted form-hint">可只写 6 位代码,自动补交易所后缀(.SSE / .SZSE)</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="K 线周期">
|
||||
<el-input v-model="form.interval" placeholder="15m" style="width: 160px" />
|
||||
<span class="muted form-hint">如 15m / 1m / d</span>
|
||||
<el-select v-model="form.interval" style="width: 220px">
|
||||
<el-option v-for="o in INTERVAL_OPTIONS" :key="o.value" :value="o.value" :label="o.label">
|
||||
<span>{{ o.label }}</span>
|
||||
<span v-if="!o.replayOk" class="muted" style="float: right; font-size: 12px">影子柜台实时可用·回放暂无本地数据</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<span class="muted form-hint">miniQMT 成品K线,默认日线</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ElMessage } from 'element-plus'
|
||||
import { createPaper, type PaperCreate } from '@/api/paper'
|
||||
import { apiClient } from '@/api/client'
|
||||
import { getStrategies, type StrategyItem } from '@/api/strategy'
|
||||
import { INTERVAL_OPTIONS } from '@/constants/intervals'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -85,10 +86,6 @@ const modes = [
|
||||
{ value: 'replay', label: '回放', desc: '历史重放,立即出结果' },
|
||||
{ value: 'live', label: '实走', desc: '每日定时 step,长期跟踪' },
|
||||
]
|
||||
const intervals = [
|
||||
{ value: 'd', label: '日频' },
|
||||
{ value: '15m', label: '15 分钟' },
|
||||
]
|
||||
const sessions = [
|
||||
{ value: 'next_open', label: '次日开盘', desc: '收盘型信号,T+1 开盘撮合' },
|
||||
{ value: 'current_close', label: '当日收盘', desc: '尾盘型信号,当日收盘撮合' },
|
||||
@@ -209,10 +206,17 @@ function onSymbols(v: string): void {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!isPortfolio" class="seg-label" style="margin-top:16px">频率</div>
|
||||
<el-radio-group v-if="!isPortfolio" v-model="form.interval">
|
||||
<el-radio-button v-for="i in intervals" :key="i.value" :value="i.value">{{ i.label }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div v-if="!isPortfolio" class="seg-label" style="margin-top:16px">K 线周期</div>
|
||||
<el-select v-if="!isPortfolio" v-model="form.interval" style="width: 220px">
|
||||
<el-option v-for="i in INTERVAL_OPTIONS" :key="i.value"
|
||||
:value="i.value" :label="i.label">
|
||||
<span>{{ i.label }}</span>
|
||||
<span v-if="!i.replayOk" class="muted" style="float:right;font-size:12px">影子柜台实时可用·回放暂无本地数据</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div v-if="!isPortfolio" class="muted" style="font-size:12px;margin-top:4px">
|
||||
{{ INTERVAL_OPTIONS.find(o => o.value === form.interval)?.matchHint || (form.interval === 'd' ? '' : '分钟级周期需标的分钟数据') }}
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="blk" shadow="never">
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getParams } from '@/api/strategy'
|
||||
import { INTERVAL_OPTIONS } from '@/constants/intervals'
|
||||
import { apiClient } from '@/api/client'
|
||||
|
||||
interface CodeFile {
|
||||
@@ -49,10 +50,7 @@ const POOL_OPTIONS = [
|
||||
{ label: '中证2000', value: 'ZZ2000' },
|
||||
{ label: '全市场', value: 'ALL' },
|
||||
]
|
||||
const INTERVAL_OPTIONS = [
|
||||
{ label: '日线', value: 'd', matchHint: '每日 1 个撮合点' },
|
||||
{ label: '15 分钟', value: '15m', matchHint: '每日约 16 个撮合点(每根 15m K线撮合)' },
|
||||
]
|
||||
// miniQMT 成品K线周期全量选项(共享常量,默认日线)
|
||||
const SESSION_OPTIONS = [
|
||||
{ label: '下一根 K线 · 开盘价(防未来函数,推荐)', value: 'next_open', dayOnly: false },
|
||||
{ label: '当前 K线 · 收盘价', value: 'current_close', dayOnly: false },
|
||||
@@ -220,9 +218,12 @@ async function onDelete(): Promise<void> {
|
||||
<template #header><span class="section-title">撮合 · 精度与时点</span></template>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="数据精度">
|
||||
<el-radio-group v-model="form.interval">
|
||||
<el-radio-button v-for="o in INTERVAL_OPTIONS" :key="o.value" :value="o.value">{{ o.label }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-select v-model="form.interval" style="width: 220px">
|
||||
<el-option v-for="o in INTERVAL_OPTIONS" :key="o.value" :value="o.value" :label="o.label">
|
||||
<span>{{ o.label }}</span>
|
||||
<span v-if="!o.replayOk" class="muted" style="float: right; font-size: 12px">影子柜台实时可用·回放暂无本地数据</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<span class="muted form-hint">撮合频率 = 精度 · {{ matchHint }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="撮合时点">
|
||||
|
||||
Reference in New Issue
Block a user