|
@@ -0,0 +1,226 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <lay-card class="custom-card">
|
|
|
|
|
+ <template v-slot:title>
|
|
|
|
|
+ <span class="card-title">币对分数排名</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-slot:body>
|
|
|
|
|
+ <div class="custom-form-layout">
|
|
|
|
|
+ <lay-form class="form-wp" :model="pageParams" mode="inline" size="sm">
|
|
|
|
|
+ <lay-form-item label="盘口" prop="exchange">
|
|
|
|
|
+ <lay-select v-model="pageParams.exchange" :show-search="true">
|
|
|
|
|
+ <lay-select-option v-for="item of rkExchanges" :value="item" :label="item" />
|
|
|
|
|
+ </lay-select>
|
|
|
|
|
+ </lay-form-item>
|
|
|
|
|
+ <lay-form-item label="波动分数≥" prop="msvScore">
|
|
|
|
|
+ <lay-input v-model="pageParams.msvScore" />
|
|
|
|
|
+ </lay-form-item>
|
|
|
|
|
+ <lay-form-item label="交易量分数≥" prop="liquidityScore">
|
|
|
|
|
+ <lay-input v-model="pageParams.liquidityScore" />
|
|
|
|
|
+ </lay-form-item>
|
|
|
|
|
+ <lay-form-item label="交易频次分数≥" prop="frequencyScore">
|
|
|
|
|
+ <lay-input v-model="pageParams.frequencyScore" />
|
|
|
|
|
+ </lay-form-item>
|
|
|
|
|
+ <lay-form-item label="总评分≥" prop="sumScore">
|
|
|
|
|
+ <lay-input v-model="pageParams.sumScore" />
|
|
|
|
|
+ </lay-form-item>
|
|
|
|
|
+ <div class="form-button-wp">
|
|
|
|
|
+ <lay-button @click="getPageInfo()">搜索</lay-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </lay-form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <lay-table :page="tablePage" size="sm" :columns="columns" resize :data-source="dataShowSource" :loading="pageConfig.loading" @change="handleCurrentChange" @sortChange="handleSortChange">
|
|
|
|
|
+ <template v-slot:msvScore="{ row }">
|
|
|
|
|
+ <span class="primary-color">{{ row.msv_score }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-slot:liquidityScore="{ row }">
|
|
|
|
|
+ <span class="normal-color">{{ row.liquidity_score }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-slot:frequencyScore="{ row }">
|
|
|
|
|
+ <span class="warm-color">{{ row.frequency_score }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-slot:score="{ row }">
|
|
|
|
|
+ <span class="danger-color">{{ row.score }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-slot:operator="{ row }">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <TableButton text="查看MSV" @click="toJump(row)" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </lay-table>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </lay-card>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script lang="ts" setup name="IndicatorSymbolRankReal">
|
|
|
|
|
+import { ref, reactive } from "vue";
|
|
|
|
|
+import { useRouter } from "vue-router";
|
|
|
|
|
+import TableButton from "@/components/TableButton.vue";
|
|
|
|
|
+import { get_exchange_rank, get_symbols_rank_real } from "@/api";
|
|
|
|
|
+
|
|
|
|
|
+const router = useRouter();
|
|
|
|
|
+
|
|
|
|
|
+interface PageConfig {
|
|
|
|
|
+ loading: boolean;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+let pageConfig: PageConfig = reactive({
|
|
|
|
|
+ loading: false,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+interface FormItem {
|
|
|
|
|
+ exchange?: string;
|
|
|
|
|
+ msvScore?: string;
|
|
|
|
|
+ liquidityScore?: string;
|
|
|
|
|
+ frequencyScore?: string;
|
|
|
|
|
+ sumScore?: string;
|
|
|
|
|
+}
|
|
|
|
|
+const pageParams: FormItem = reactive({ exchange: "gate_usdt_swap" });
|
|
|
|
|
+
|
|
|
|
|
+interface TablePage {
|
|
|
|
|
+ current: number;
|
|
|
|
|
+ limit: number;
|
|
|
|
|
+ total: number;
|
|
|
|
|
+}
|
|
|
|
|
+const tablePage: TablePage = reactive({ current: 1, limit: 20, total: 0, limits: [20, 50, 100, 200, 500] });
|
|
|
|
|
+const columns = ref([
|
|
|
|
|
+ { title: "币对", width: "110", key: "symbol", ellipsisTooltip: true },
|
|
|
|
|
+ { title: "最大Abs(波动率)", key: "msv_abs_max" },
|
|
|
|
|
+ { title: "平均Abs(波动率)", key: "msv_abs_avg" },
|
|
|
|
|
+ { title: "有效波动次数", key: "effective_count" },
|
|
|
|
|
+ { title: "平均行情推动量", key: "liquidity_avg" },
|
|
|
|
|
+ { title: "Sum(Abs(波动率))", key: "msv_abs_total" },
|
|
|
|
|
+ { title: "Sum(预期利润)", key: "epr_total" },
|
|
|
|
|
+ { title: "波动分数", width: "80", key: "msv_score", customSlot: "msvScore", ellipsisTooltip: true },
|
|
|
|
|
+ { title: "交易量分数", width: "100", key: "liquidity_score", customSlot: "liquidityScore" },
|
|
|
|
|
+ { title: "交易频次分数", width: "100", key: "frequency_score", customSlot: "frequencyScore" },
|
|
|
|
|
+ { title: "总评分", width: "80", key: "score", customSlot: "score", sort: "desc" },
|
|
|
|
|
+ { title: "开仓值", width: "90", key: "coverted_open_base", ellipsisTooltip: true },
|
|
|
|
|
+ { title: "操作", width: "90", key: "operator", customSlot: "operator" },
|
|
|
|
|
+]);
|
|
|
|
|
+let dataSource = ref<any>([]);
|
|
|
|
|
+let dataShowSource = ref<any>([]);
|
|
|
|
|
+let dataSortSource = ref<any>([]);
|
|
|
|
|
+let sortInfo = ref<any>({});
|
|
|
|
|
+
|
|
|
|
|
+let rkExchanges = ref<any>([]);
|
|
|
|
|
+
|
|
|
|
|
+const getRkExchanges = () => {
|
|
|
|
|
+ const params = {};
|
|
|
|
|
+ pageConfig.loading = true;
|
|
|
|
|
+ get_exchange_rank(params, (data: any) => {
|
|
|
|
|
+ pageConfig.loading = false;
|
|
|
|
|
+ if (data.code == 200) {
|
|
|
|
|
+ rkExchanges.value = data.data;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
+getRkExchanges();
|
|
|
|
|
+
|
|
|
|
|
+// 请求交易所列表
|
|
|
|
|
+const getPageInfo = () => {
|
|
|
|
|
+ tablePage.current = 1;
|
|
|
|
|
+ tablePage.total = 0;
|
|
|
|
|
+ dataSource.value = [];
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ exchange: pageParams.exchange,
|
|
|
|
|
+ };
|
|
|
|
|
+ pageConfig.loading = true;
|
|
|
|
|
+ get_symbols_rank_real(params, (data: any) => {
|
|
|
|
|
+ pageConfig.loading = false;
|
|
|
|
|
+ if (data.code == 200) {
|
|
|
|
|
+ let source = data.data.filter((item: any) => {
|
|
|
|
|
+ let msvScore = parseFloat(pageParams.msvScore || "0");
|
|
|
|
|
+ let liquidityScore = parseFloat(pageParams.liquidityScore || "0");
|
|
|
|
|
+ let frequencyScore = parseFloat(pageParams.frequencyScore || "0");
|
|
|
|
|
+ let sumScore = parseFloat(pageParams.sumScore || "0");
|
|
|
|
|
+ return item.msv_score >= msvScore && item.liquidity_score >= liquidityScore && item.frequency_score >= frequencyScore && item.score >= sumScore;
|
|
|
|
|
+ });
|
|
|
|
|
+ tablePage.total = source.length;
|
|
|
|
|
+ dataSource.value = source;
|
|
|
|
|
+ handleSortChange(sortInfo.value.key, sortInfo.value.sort);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
+getPageInfo();
|
|
|
|
|
+
|
|
|
|
|
+const toJump = (value: any) => {
|
|
|
|
|
+ router.push({ path: "/indicator/msv", query: { symbol: value.symbol, exchange: pageParams.exchange, minute_time_range: 70 } });
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 分页设置
|
|
|
|
|
+const handleCurrentChange = (val: any) => {
|
|
|
|
|
+ dataShowSource.value = [...dataSortSource.value.slice((val.current - 1) * val.limit, val.current * val.limit)];
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 排序
|
|
|
|
|
+const handleSortChange = (key: any, sort: any) => {
|
|
|
|
|
+ sortInfo.value = { key, sort };
|
|
|
|
|
+ if (!sort) {
|
|
|
|
|
+ dataSortSource.value = [...dataSource.value];
|
|
|
|
|
+ dataShowSource.value = [...dataSource.value.slice((tablePage.current - 1) * tablePage.limit, tablePage.current * tablePage.limit)];
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ dataSortSource.value = [...dataSource.value].sort((a: any, b: any) => {
|
|
|
|
|
+ let maxA = -9999999;
|
|
|
|
|
+ let maxB = -9999999;
|
|
|
|
|
+ Object.values(a[key]).map((item) => (maxA = Number(item) > maxA ? Number(item) : maxA));
|
|
|
|
|
+ Object.values(b[key]).map((item) => (maxB = Number(item) > maxB ? Number(item) : maxB));
|
|
|
|
|
+ return maxA - maxB;
|
|
|
|
|
+ });
|
|
|
|
|
+ if (sort == "desc") dataSortSource.value.reverse();
|
|
|
|
|
+ dataShowSource.value = [...dataSortSource.value.slice((tablePage.current - 1) * tablePage.limit, tablePage.current * tablePage.limit)];
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.custom-form-layout {
|
|
|
|
|
+ .custom-card-checkbox,
|
|
|
|
|
+ .custom-checkbox {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+ padding-right: 20px;
|
|
|
|
|
+ .label {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ padding-right: 15px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .checkbox-group {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ .checkbox-wp {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-right: 10px;
|
|
|
|
|
+ line-height: 38px;
|
|
|
|
|
+ :deep(.layui-checkbox-label) {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ :deep(.layui-form-radio) {
|
|
|
|
|
+ margin-top: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ :deep(.layui-checkcard) {
|
|
|
|
|
+ padding: 0 10px;
|
|
|
|
|
+ width: auto;
|
|
|
|
|
+ margin: 0 10px 0 0;
|
|
|
|
|
+ .layui-checkcard-content {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .checkbox-input {
|
|
|
|
|
+ width: 40px;
|
|
|
|
|
+ }
|
|
|
|
|
+ &:last-child {
|
|
|
|
|
+ margin-right: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .custom-card-checkbox {
|
|
|
|
|
+ .checkbox-wp {
|
|
|
|
|
+ padding: 0 20px;
|
|
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|