Browse Source

添加爆仓指标

DESKTOP-NE65RNK\Citrus_limon 9 months ago
parent
commit
4621cd3ee1
2 changed files with 250 additions and 0 deletions
  1. 7 0
      src/router/routes.ts
  2. 243 0
      src/views/indicator/fot/index.vue

+ 7 - 0
src/router/routes.ts

@@ -82,6 +82,13 @@ const routes: Array<RouteRecordRaw> = [
         component: () => import("@/views/indicator/msv/index.vue"),
         meta: { title: "波动率指标", keepAlive: true },
       },
+      {
+        path: "/indicator/fot",
+        name: "IndicatorFot",
+
+        component: () => import("@/views/indicator/fot/index.vue"),
+        meta: { title: "爆仓指标", keepAlive: true },
+      },
       {
         path: "/indicator/symbol_filter",
         name: "IndicatorSymbolFilter",

+ 243 - 0
src/views/indicator/fot/index.vue

@@ -0,0 +1,243 @@
+<template>
+  <lay-card class="custom-card">
+    <template v-slot:title>
+      <span class="card-title">爆仓指标</span>
+    </template>
+
+    <template v-slot:body>
+      <lay-loading class="custom-loading" :loading="pageConfig.loading">
+        <div class="custom-form-layout">
+          <lay-form class="form-wp" :model="pageParams" mode="inline" size="sm">
+            <lay-form-item label="币对" prop="symbol">
+              <lay-input v-model="pageParams.symbol" />
+            </lay-form-item>
+            <lay-form-item label="盘口" prop="exchange">
+              <lay-select v-model="pageParams.exchange" :show-search="true" allowClear>
+                <lay-select-option v-for="item of iaExchanges" :value="item" :label="item" />
+              </lay-select>
+            </lay-form-item>
+            <lay-form-item label="查询时间" prop="minute_time_range">
+              <lay-input v-model="pageParams.minute_time_range" placeholder="查询时间(分钟)" />
+            </lay-form-item>
+            <lay-form-item label="阈值" prop="value_ln">
+              <lay-input v-model="pageParams.value_ln" placeholder="阈值" />
+            </lay-form-item>
+            <lay-form-item>
+              <lay-button @click="getMsvData()">查询</lay-button>
+            </lay-form-item>
+          </lay-form>
+        </div>
+        <div>
+          <div class="chart" ref="chartRef"></div>
+        </div>
+      </lay-loading>
+    </template>
+  </lay-card>
+</template>
+
+<script lang="ts" setup name="IndicatorMsv">
+import { ref, reactive, onUnmounted, shallowRef } from "vue";
+import * as echarts from "echarts";
+import { get_indicator, get_ia_exchanges } from "@/api";
+
+const chartRef = ref();
+const tradesRef = ref();
+
+interface PageConfig {
+  loading: boolean;
+}
+
+interface FormItem {
+  symbol?: String;
+  exchange?: String;
+  minute_time_range?: String;
+  value_ln?: String;
+}
+
+let pageConfig: PageConfig = reactive({
+  loading: false,
+});
+
+let symbol: any = "btc_usdt";
+let exchange: any = "binance_usdt_swap";
+let minute_time_range: any = "30";
+let value_ln: any = "10";
+
+const pageParams: FormItem = reactive({ symbol, exchange, minute_time_range, value_ln });
+
+let iaExchanges = ref<any>([]);
+const getIaExchanges = () => {
+  const params = {};
+  pageConfig.loading = true;
+  get_ia_exchanges(params, (data: any) => {
+    pageConfig.loading = false;
+    if (data.code == 200) {
+      iaExchanges.value = data.data;
+    }
+  });
+};
+getIaExchanges();
+
+let msvChart = shallowRef();
+
+const getMsvData = () => {
+  const params = { indicator: "fot", query: pageParams };
+  pageConfig.loading = true;
+  get_indicator(params, (data: any) => {
+    pageConfig.loading = false;
+    if (data.code == 200) {
+      initChart(data.data);
+    }
+  });
+};
+getMsvData();
+
+const initChart = (data: any) => {
+  if (msvChart.value != null && !msvChart.value.isDisposed()) echarts.dispose(msvChart.value);
+
+  msvChart.value = echarts.init(chartRef.value);
+
+  window.removeEventListener("resize", () => msvChart.value.resize());
+  window.addEventListener("resize", () => msvChart.value.resize());
+
+  let lineSeriesData = data.profits.map((item: any, index: number) => ({ name: `折线${index + 1}`, type: "line", symbol: "none", data: item }));
+  let barSeriesData = [
+    {
+      name: "柱状图",
+      type: "line",
+      color: "rgb(55, 162, 255)",
+      data: data.profit_total_list,
+      xAxisIndex: 1,
+      yAxisIndex: 1,
+      areaStyle: {
+        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+          {
+            offset: 0,
+            color: "rgb(55, 162, 255)",
+          },
+          {
+            offset: 1,
+            color: "rgb(55, 162, 255)",
+          },
+        ]),
+      },
+    },
+  ];
+  const chartOption = {
+    title: [
+      {
+        text: `${pageParams.exchange} ${pageParams.symbol?.toUpperCase()} ${parseFloat(((Number(pageParams.minute_time_range) || 240) / 60).toFixed(2)).toString()}小时波动幅度指标`,
+        textStyle: {
+          fontSize: 20,
+        },
+      },
+    ],
+    grid: [
+      {
+        top: "100px",
+        left: "60px",
+        right: "60px",
+        height: "40%", // 主图高度
+        backgroundColor: "red",
+      },
+      {
+        left: "60px",
+        right: "60px",
+        bottom: "100px",
+        height: "25%", // 副图高度
+      },
+    ],
+    dataZoom: [
+      {
+        type: "inside",
+        xAxisIndex: [0, 1],
+        start: 0,
+        end: 100,
+      },
+      {
+        xAxisIndex: [0, 1],
+        start: 0,
+        end: 100,
+      },
+    ],
+    tooltip: {
+      trigger: "axis",
+      axisPointer: {
+        type: "cross",
+      },
+      formatter: (params: any) => {
+        if (params.length === 0) return "";
+      },
+    },
+    xAxis: [
+      {
+        type: "category",
+        boundaryGap: false,
+        show: true,
+      },
+      {
+        type: "category",
+        gridIndex: 1, // 垂直副图的网格索引
+        show: true, // 不显示副图的 x 轴
+      },
+    ],
+    yAxis: [
+      {
+        type: "value",
+      },
+      {
+        gridIndex: 1, // 垂直副图的网格索引
+        type: "value", // 副图的 y 轴
+      },
+    ],
+    series: [...lineSeriesData, ...barSeriesData],
+  };
+  msvChart.value.setOption(chartOption);
+  // 绑定鼠标点击事件
+  msvChart.value.getZr().on("click", (event: any) => {
+    const pointInPixel = [event.offsetX, event.offsetY];
+    const pointInGrid = msvChart.value?.convertFromPixel({ seriesIndex: 0 }, pointInPixel);
+
+    if (pointInGrid) {
+      const xIndex = Math.round(pointInGrid[0]);
+      const xAxisData = msvChart.value?.getOption().series[0].data[xIndex];
+      const time = xAxisData[0];
+      const query = {
+        exchange: pageParams.exchange,
+        symbol: pageParams.symbol,
+        start_time_mills: (time * 1 - 60000).toString(),
+        end_time_mills: (time * 1 + 60000).toString(),
+      };
+      tradesRef.value.show(query);
+    }
+  });
+};
+onUnmounted(() => {
+  window.removeEventListener("resize", () => msvChart.value.resize());
+});
+</script>
+
+<style lang="scss" scoped>
+.custom-card {
+  min-width: 256px;
+}
+.chart {
+  padding-top: 20px;
+  min-height: 800px;
+}
+.robot-info-header {
+  background-color: white;
+  padding: 16px 24px;
+  margin-bottom: 20px;
+  .robot-name {
+    font-size: 14px;
+    font-weight: bold;
+  }
+  .robot-status {
+    span {
+      font-size: 12px;
+      padding-left: 4px;
+    }
+  }
+}
+</style>