iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
SideProject30

Nuxt3的初心者之旅:淬鍊出屬於自己的金融投資儀表板系列 第 16

DAY16 - 多重圖表宇宙 - Nuxt3建立複數股票技術分析圖表(2)

  • 分享至 

  • xImage
  •  

今日工事

完成技術指標(包含覆蓋指標振蕩指標)
並可任意更換想要看的技術指標

技術指標(價格通道&移動平均線)

// highcharts.client.js
import HighchartsVue from 'highcharts-vue'
import StockModule from "highcharts/modules/stock";
import Highcharts from "highcharts";
import axios from 'axios'
import VueAxios from 'vue-axios'
import SimpleTypeahead from 'vue3-simple-typeahead';

import pc from "highcharts/indicators/price-channel";
import macd from 'highcharts/indicators/macd';

export default defineNuxtPlugin((nuxtApp) => {
  // 股票模組化
  StockModule(Highcharts)
  indicators(Highcharts)
  pc(Highcharts)

  macd(Highcharts)

  nuxtApp.vueApp.use(HighchartsVue)
    .use(VueAxios, axios)
    .provide('axios', axios)  // provide 'axios'
    .use(SimpleTypeahead)
})

// [id].vue
const route = useRoute()
const id = route.params.id

const chartOptions = computed(() => {
  return {
    // ...略
    series: [
       {
        type: 'candlestick',
        id: `${id}`,
        name: `${id}`,
        data: ohlc.value,
      },
    // ...略
      {
        type: 'pc',         //資料種類
        id: 'overlay',      //呈現出來資料節點的id 
        linkedTo: `${id}`,  //主要指標基於的資料id
        yAxis: 0,           //放在Y軸的位置
      },
      {
        type: 'macd',
        id: 'oscillator',
        linkedTo: `${id}`,
        yAxis: 2,
      },
    ],
  }
})

首先在series資料裡面新增常用的兩個類型
PC(價格通道)跟MACD(移動平均線)
其中linkedTo的id就是它要根據哪個資料去做技術分析的依據
這邊對到的就是candlestick的資料

這樣就完成了嗎?
我也希望(苦笑)

https://ithelp.ithome.com.tw/upload/images/20231001/20162573ZDNZdIw28u.png

missingModuleFor: pc
還要在安裝該技術指標對應的模組
highchart才會有該類型
所以要把它們import進來

import pc from 'highcharts/indicators/price-channel';
import macd from 'highcharts/indicators/macd';

再安裝該模組

pc(Highcharts)
macd(Highcharts)

https://ithelp.ithome.com.tw/upload/images/20231001/20162573Fb5ol8VSsc.png

更換成其他指標

// highcharts.client.js
import HighchartsVue from 'highcharts-vue'
import StockModule from "highcharts/modules/stock";
import Highcharts from "highcharts";

import indicators from 'highcharts/indicators/indicators';
import pc from 'highcharts/indicators/price-channel';
import vwap from 'highcharts/indicators/vwap';
import pe from 'highcharts/indicators/price-envelopes';
import regressions from 'highcharts/indicators/regressions';
import pivotpoints from 'highcharts/indicators/pivot-points';
import vbp from 'highcharts/indicators/volume-by-price';
import wma from 'highcharts/indicators/wma';

import macd from 'highcharts/indicators/macd';
import ao from 'highcharts/indicators/ao';
import atr from 'highcharts/indicators/atr';
import cci from 'highcharts/indicators/cci';
import disparityIndex from 'highcharts/indicators/disparity-index';
import dmi from 'highcharts/indicators/dmi';
import mfi from 'highcharts/indicators/mfi';
import rsi from 'highcharts/indicators/rsi';

export default defineNuxtPlugin((nuxtApp) => {
  // 股票模組化
  StockModule(Highcharts)
  indicators(Highcharts)
  pc(Highcharts)
  vwap(Highcharts)
  pe(Highcharts)
  regressions(Highcharts)
  pivotpoints(Highcharts)
  vbp(Highcharts)
  wma(Highcharts)

  macd(Highcharts)
  ao(Highcharts)
  atr(Highcharts)
  cci(Highcharts)
  disparityIndex(Highcharts)
  dmi(Highcharts)
  mfi(Highcharts)
  rsi(Highcharts)

  nuxtApp.vueApp.use(HighchartsVue)
    .use(VueAxios, axios)
    .provide('axios', axios)  // provide 'axios'
    .use(SimpleTypeahead)
}
// [id].vue

<div class="flex w-[100%] ms-3">
      <div class="my-1 w-[50%]">
        <label for="overlays">覆蓋指標:</label>
        <select class="border border-solid border-black rounded shadow ms-2" id="overlays" @change="overlaysChoose">
          <option value="ema">EMA (Exponential Moving Average)</option>
          <option value="linearRegression">Linear Regression</option>
          <option value="pivotpoints">Pivot Points</option>
          <option value="pc" selected="selected">Price Channel</option>
          <option value="priceenvelopes">Price Envelopes</option>
          <option value="sma">SMA (Simple Moving Average)</option>
          <option value="vbp">VbP (Volume by Price)</option>
          <option value="wma">WMA (Weighted Moving Average)</option>
          <option value="vwap">VWAP (Volume Weighted Average Price)</option>
        </select>
      </div>
      <div class="my-1">
        <label for="oscillators">振蕩指標:</label>
        <select class="border border-solid border-black rounded shadow ms-2" id="oscillators" @change="OscillatorChoose">
          <option value="atr">ATR (Average True Range)</option>
          <option value="ao">Awesome oscillator</option>
          <option value="cci">CCI (Commodity Channel Index)</option>
          <option value="disparityindex">Disparity Index</option>
          <option value="dmi">DMI (Directional Movement Index)</option>
          <option value="macd" selected="selected">
            MACD (Moving Average Convergence Divergence)
          </option>
          <option value="mfi">MFI (Money Flow Index)</option>
          <option value="rsi">RSI (Relative Strength Index)</option>
        </select>
      </div>
    </div>
    <ClientOnly>
      <highcharts
        v-if="ohlc.length !== 0"
        class="w-[1000px] mx-auto my-10"
        :constructor-type="'stockChart'"
        :options="chartOptions"
        :callback="afterChartInit"
      />
</ClientOnly>

<script setup>
// 技術指標
const overlaysChoose = ref()
const OscillatorChoose = ref()

// 股票圖表建立後可用的內建function
const afterChartInit = (chart) => {
  
  // 更換覆蓋指標
  const overlays = (e) => {
    var series = chart.get('overlay')
    if (series) {
      series.remove(false)
      chart.addSeries({
        type: e.target.value,
        linkedTo: `${id}`,
        id: 'overlay',
      })
    }
  }

  // 更換技術指標
  const oscillator = (e) => {
    var series = chart.get('oscillator')
    if (series) {
      series.remove(false)
      chart.addSeries({
        type: e.target.value,
        linkedTo: `${id}`,
        id: 'oscillator',
        yAxis: 2,
      })
    }
  }
  overlaysChoose.value = overlays
  OscillatorChoose.value = oscillator
}
})

</script>

highchart可以安裝的技術指標蠻齊全的
我只裝常用來判斷的指標
並且先把select的選項先給做好
到這一步還算簡單

再來
要怎麼抓取PCMACD的節點並把它更換成我要的技術線圖呢?

這邊引用highcharts-vue對元件的說明

Chart callback parameter
If you need to use callback from Highcharts.chart(renderTo, options [, callback]) function, you could pass it by :callback parameter through HTML component element:

<highcharts :options="chartOptions" :callback="someFunction">
Then, someFunction will be called when chart is loaded.

利用highcharts component的callback function
去使用圖表建立後可以用的方法
其中有個chart.get()
參數把要抓取的id放入就可以抓到該圖表
之後再用series.remove(false)把舊圖表移除
chart.addSeries把新的圖表加上去

更換技術指標的function寫好後
因為callback在圖表建立後會自動執行
所以把function賦予到外面的變數
在綁定change事件

@change="overlaysChoose"
@change="OscillatorChoose"

就大功告成啦!!

https://ithelp.ithome.com.tw/upload/images/20231001/20162573qZjfRhn7UQ.png

https://ithelp.ithome.com.tw/upload/images/20231001/20162573zsWtE7NxMQ.png

小結:

在圖表實例化後取得的方法那邊卡了蠻久
官網的介紹都不是從元件裡取出的方法
而是用原生的chart在div建立後才能取得
自己try很久才摸出來
不過成就感也是加倍的

感謝中秋連假~

參考文件:

highcharts-vue

highstockApi


上一篇
DAY15 - 多重圖表宇宙 - Nuxt3建立複數股票技術分析圖表(1)
下一篇
DAY17 - 誰是賠錢貨- Nuxt3建立HighChart股票績效比較圖(1)
系列文
Nuxt3的初心者之旅:淬鍊出屬於自己的金融投資儀表板30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言