cta strategy init
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
"CTA strategy"
|
||||||
|
|
||||||
|
"strategy list"
|
||||||
|
const get_strategy_list = () => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
"upload a strategy"
|
||||||
|
const upload_strategy = () => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
"load a strategy"
|
||||||
|
const load_strategy = (strategy_id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
"unload a strategy"
|
||||||
|
const unload_strategy = (strategy_id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
"start a strategy"
|
||||||
|
const start_strategy = (strategy_id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
"stop a strategy"
|
||||||
|
const stop_strategy = (strategy_id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
"remove a strategy"
|
||||||
|
const remove_strategy = (strategy_id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
get_strategy_list,
|
||||||
|
upload_strategy,
|
||||||
|
load_strategy,
|
||||||
|
unload_strategy,
|
||||||
|
start_strategy,
|
||||||
|
stop_strategy,
|
||||||
|
remove_strategy
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
const get_stock_data = (data: Object) => {
|
||||||
|
return request({
|
||||||
|
url: '/auth/api/v1/trader',
|
||||||
|
method: 'PUT',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export { get_stock_data }
|
||||||
@@ -49,7 +49,7 @@ const doLogin = () => {
|
|||||||
}
|
}
|
||||||
const doLogout = () => {
|
const doLogout = () => {
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
logout(tenant.id).then(() => {
|
logout(tenant.id).catch(() => { console.log(1) }).finally(() => {
|
||||||
tenant.logout()
|
tenant.logout()
|
||||||
router.push({
|
router.push({
|
||||||
path: '/login'
|
path: '/login'
|
||||||
|
|||||||
@@ -61,6 +61,13 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: '一键打包'
|
name: '一键打包'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/trader',
|
||||||
|
component: () => import('../view/trader/index.vue'),
|
||||||
|
meta: {
|
||||||
|
name: 'trader'
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
import * as echarts from 'echarts'
|
||||||
|
const upColor = '#ec0000'
|
||||||
|
const upBorderColor = '#8A0000'
|
||||||
|
const downColor = '#00da3c'
|
||||||
|
const downBorderColor = '#008F28'
|
||||||
|
import { EChartsOption } from 'echarts'
|
||||||
|
|
||||||
|
type DataItem = [string, number, number, number, number, number, number];
|
||||||
|
|
||||||
|
const option: EChartsOption = {
|
||||||
|
dataset: {
|
||||||
|
source: []
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: ''
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'line'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbox: {
|
||||||
|
feature: {
|
||||||
|
dataZoom: {
|
||||||
|
yAxisIndex: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: [
|
||||||
|
{
|
||||||
|
left: '10%',
|
||||||
|
right: '10%',
|
||||||
|
bottom: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
left: '10%',
|
||||||
|
right: '10%',
|
||||||
|
height: 80,
|
||||||
|
bottom: 80
|
||||||
|
}
|
||||||
|
],
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
// inverse: true,
|
||||||
|
axisLine: { onZero: false },
|
||||||
|
splitLine: { show: false },
|
||||||
|
min: 'dataMin',
|
||||||
|
max: 'dataMax'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
gridIndex: 1,
|
||||||
|
boundaryGap: false,
|
||||||
|
axisLine: { onZero: false },
|
||||||
|
axisTick: { show: false },
|
||||||
|
splitLine: { show: false },
|
||||||
|
axisLabel: { show: false },
|
||||||
|
min: 'dataMin',
|
||||||
|
max: 'dataMax'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
scale: true,
|
||||||
|
splitArea: {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scale: true,
|
||||||
|
gridIndex: 1,
|
||||||
|
splitNumber: 2,
|
||||||
|
axisLabel: { show: false },
|
||||||
|
axisLine: { show: false },
|
||||||
|
axisTick: { show: false },
|
||||||
|
splitLine: { show: false }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
xAxisIndex: [0, 1],
|
||||||
|
start: 10,
|
||||||
|
end: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
show: true,
|
||||||
|
xAxisIndex: [0, 1],
|
||||||
|
type: 'slider',
|
||||||
|
bottom: 10,
|
||||||
|
start: 10,
|
||||||
|
end: 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
visualMap: {
|
||||||
|
show: false,
|
||||||
|
seriesIndex: 1,
|
||||||
|
dimension: 6,
|
||||||
|
pieces: [
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
color: upColor
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: -1,
|
||||||
|
color: downColor
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'candlestick',
|
||||||
|
itemStyle: {
|
||||||
|
color: upColor,
|
||||||
|
color0: downColor,
|
||||||
|
borderColor: upBorderColor,
|
||||||
|
borderColor0: downBorderColor
|
||||||
|
},
|
||||||
|
encode: {
|
||||||
|
x: 0,
|
||||||
|
y: [1, 4, 3, 2]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Volumn',
|
||||||
|
type: 'bar',
|
||||||
|
xAxisIndex: 1,
|
||||||
|
yAxisIndex: 1,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#7fbe9e'
|
||||||
|
},
|
||||||
|
large: true,
|
||||||
|
encode: {
|
||||||
|
x: 0,
|
||||||
|
y: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateOHLC = (count: number) => {
|
||||||
|
let data: DataItem[] = [];
|
||||||
|
|
||||||
|
let xValue = +new Date(2011, 0, 1);
|
||||||
|
let minute = 60 * 1000;
|
||||||
|
let baseValue = Math.random() * 12000;
|
||||||
|
let boxVals = new Array(4);
|
||||||
|
let dayRange = 12;
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
baseValue = baseValue + Math.random() * 20 - 10;
|
||||||
|
|
||||||
|
for (let j = 0; j < 4; j++) {
|
||||||
|
boxVals[j] = (Math.random() - 0.5) * dayRange + baseValue;
|
||||||
|
}
|
||||||
|
boxVals.sort();
|
||||||
|
|
||||||
|
let openIdx = Math.round(Math.random() * 3);
|
||||||
|
let closeIdx = Math.round(Math.random() * 2);
|
||||||
|
if (closeIdx === openIdx) {
|
||||||
|
closeIdx++;
|
||||||
|
}
|
||||||
|
let volumn = boxVals[3] * (1000 + Math.random() * 500);
|
||||||
|
|
||||||
|
// ['open', 'close', 'lowest', 'highest', 'volumn']
|
||||||
|
// [1, 4, 3, 2]
|
||||||
|
data[i] = [
|
||||||
|
echarts.format.formatTime('yyyy-MM-dd\nhh:mm:ss', (xValue += minute)),
|
||||||
|
+boxVals[openIdx].toFixed(2), // open
|
||||||
|
+boxVals[3].toFixed(2), // highest
|
||||||
|
+boxVals[0].toFixed(2), // lowest
|
||||||
|
+boxVals[closeIdx].toFixed(2), // close
|
||||||
|
+volumn.toFixed(0),
|
||||||
|
getSign(data, i, +boxVals[openIdx], +boxVals[closeIdx], 4) // sign
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSign = (
|
||||||
|
data: DataItem[],
|
||||||
|
dataIndex: number,
|
||||||
|
openVal: number,
|
||||||
|
closeVal: number,
|
||||||
|
closeDimIdx: number
|
||||||
|
) => {
|
||||||
|
var sign
|
||||||
|
if (openVal > closeVal) {
|
||||||
|
sign = -1
|
||||||
|
} else if (openVal < closeVal) {
|
||||||
|
sign = 1
|
||||||
|
} else {
|
||||||
|
sign =
|
||||||
|
dataIndex > 0
|
||||||
|
? // If close === open, compare with close of last record
|
||||||
|
data[dataIndex - 1][closeDimIdx] <= closeVal
|
||||||
|
? 1
|
||||||
|
: -1
|
||||||
|
: // No record of previous, set to be positive
|
||||||
|
1
|
||||||
|
}
|
||||||
|
return sign
|
||||||
|
}
|
||||||
|
|
||||||
|
export { generateOHLC, option }
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="about" ref="bookmarks" id="bookmarks" :style="{
|
<div class="about" ref="bookmarks" id="bookmarks" :style="{
|
||||||
width: '600px',
|
width: '600px',
|
||||||
height: '300px'
|
height: '400px'
|
||||||
}"></div>
|
}"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bookmark">
|
||||||
|
<!-- <el-form>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item>
|
||||||
|
<el-input v-model="search_form.comment" placeholder="请输入" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-button type="primary" @click="doSearch">检索</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="tag_list">
|
||||||
|
<el-tag class="ml-2 click-icon" :type="item.clicked ? 'danger' : 'info'" v-for="(item) in bookmark_types"
|
||||||
|
@click="handleTags(item)">{{ item.bk_type_name }}</el-tag>
|
||||||
|
<el-button type="primary" @click="handleAddType" v-show="Tenant.account">增加</el-button>
|
||||||
|
<el-button type="primary" @click="handleManageType" v-show="Tenant.account">自定义</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
<div class="create_dialog">
|
||||||
|
<el-button type="primary" @click="handleInsert" v-show="Tenant.account">新建</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table ref="multipleTableRef" :data="strategy_list" @selection-change="handleSelectionChange" style="width: 100%">
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<el-table-column type="index" label="index" width="80" />
|
||||||
|
<el-table-column prop="bk_type_name" label="分类" width="100" />
|
||||||
|
<el-table-column prop="comment" label="名称" width="180" />
|
||||||
|
<el-table-column prop="facvion" label="图标" width="60" />
|
||||||
|
<el-table-column class="click-icon" prop="url" label="url">
|
||||||
|
<template #default="scope">
|
||||||
|
<span style="cursor: pointer" @click="openUrl(scope.row.url)">{{ scope.row.url }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-icon :size="20" @click="copyNumber(scope.row)" class="click-icon">
|
||||||
|
<CopyDocument />
|
||||||
|
</el-icon>
|
||||||
|
<el-button class="click-icon" size="small" @click="handleEdit(scope.$index, scope.row)"
|
||||||
|
v-show="Tenant.account">编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)" v-show="Tenant.account">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div style="margin-top: 20px">
|
||||||
|
<el-button @click="toggleSelection([tableData[1], tableData[2]])">反选</el-button>
|
||||||
|
<el-button @click="toggleSelection()">清除</el-button>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- <el-dialog v-model="dialogFormVisible" title="添加书签">
|
||||||
|
<bookmark_dialog :dialog_form="currentDialogData" :operate_code="operate" :types="bookmark_types"
|
||||||
|
@on-concel="closeDialog" @on-submit="doSubmit"></bookmark_dialog>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog v-model="dialogVisible">
|
||||||
|
<delete_dialog :delete_id="currentDialogData.bk_id" @on-submit="doDelete"></delete_dialog>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog v-model="createTypeDialogVisible">
|
||||||
|
<createType_dialog @on-update="doUpdate"></createType_dialog>
|
||||||
|
</el-dialog> -->
|
||||||
|
|
||||||
|
<!-- <el-dialog v-model="typeDialogVisible">
|
||||||
|
<bookmarkType_dialog :delete_id="currentDialogData.bk_id" @on-submit="doDelete"></bookmarkType_dialog>
|
||||||
|
</el-dialog> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
import {
|
||||||
|
get_strategy_list,
|
||||||
|
upload_strategy,
|
||||||
|
load_strategy,
|
||||||
|
unload_strategy,
|
||||||
|
start_strategy,
|
||||||
|
stop_strategy,
|
||||||
|
remove_strategy
|
||||||
|
} from '../../api/cta_strategy'
|
||||||
|
|
||||||
|
|
||||||
|
type Strategy = {
|
||||||
|
strategy_id: string,
|
||||||
|
strategy_name: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const strategy_list = reactive<Strategy[]>([])
|
||||||
|
|
||||||
|
const on_list = () => {
|
||||||
|
get_strategy_list().then(res => {
|
||||||
|
res.data.forEach((item: Strategy, index: number) => {
|
||||||
|
strategy_list.push(item)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_upload = () => {
|
||||||
|
upload_strategy().then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_load = (strategy_id: string) => {
|
||||||
|
load_strategy(strategy_id).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_unload = (strategy_id: string) => {
|
||||||
|
unload_strategy(strategy_id).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_start = (strategy_id: string) => {
|
||||||
|
start_strategy(strategy_id).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_stop = (strategy_id: string) => {
|
||||||
|
stop_strategy(strategy_id).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_remove = (strategy_id: string) => {
|
||||||
|
remove_strategy(strategy_id).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="about" ref="trader_chart" id="trader_chart" :style="{
|
||||||
|
width: '1200px',
|
||||||
|
height: '600px'
|
||||||
|
}"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
import { EChartsOption } from 'echarts';
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { generateOHLC, option } from '../../service/trader'
|
||||||
|
import { get_stock_data } from '../../api/trader'
|
||||||
|
|
||||||
|
|
||||||
|
const trader_chart = ref<HTMLElement>()
|
||||||
|
|
||||||
|
const data_count = 2e5;
|
||||||
|
|
||||||
|
|
||||||
|
get_stock_data({}).then((response) => {
|
||||||
|
response.data.forEach((element: any) => {
|
||||||
|
console.log(element)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = generateOHLC(data_count);
|
||||||
|
|
||||||
|
const options = reactive<EChartsOption>(option)
|
||||||
|
|
||||||
|
""
|
||||||
|
const set_option = () => {
|
||||||
|
options.dataset = {
|
||||||
|
source: data
|
||||||
|
}
|
||||||
|
options.title = {
|
||||||
|
text: 'Data Amount: ' + echarts.format.addCommas(data_count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const on_tick = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
const on_start = () => {
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
|
||||||
|
set_option()
|
||||||
|
|
||||||
|
const myEcharts = echarts.init(trader_chart.value!)
|
||||||
|
|
||||||
|
myEcharts.setOption(options)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dashboard {
|
||||||
|
background-color: beige;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user