tvjsx / trading-vue-js

💹 Hackable charting lib for traders. You can draw literally ANYTHING on top of candlestick charts. [Not Maintained]
https://tvjsx.github.io/trading-vue-demo/
MIT License
2.07k stars 629 forks source link

Overlays set up #230

Open IlyaShkurenko opened 3 years ago

IlyaShkurenko commented 3 years ago

I'm pretty new in using this lib so things are confusing for me. I've read all docs but still can't figure out few things. How can I add SMA,EMA,RSI etc indicators on my chart and get calculated points? I've tried to do like this

this.onchart = [ // Displayed ON the chart
                {
                  "name": "EMA, 100",
                  "type": "EMA",
                  "data": this.ohlcv,
                  "settings": {
                    lineWidth: 1,
                    color: '#d1385c'
                  } // Arbitrary settings format
                }
              ];

but can't specify the range of days. I've also saw examples like this https://github.com/tvjsx/trading-vue-js/blob/master/docs/guide/OVERLAYS.md#null-overlay but don't understand how to include it on my chart.

adsonvinicius commented 3 years ago

You can find the how-to in docs, but it's cleary shown on tests/examples. It's simple:

import Overlays from 'tvjs-overlays'

data() {
...
    overlays: [
            Overlays['EMA'], 
            Overlays['BB'], 
            Overlays['MACD'],
            Overlays['RSI']
     ]
      <trading-vue 
      ...
      :overlays="overlays" 
this.chart = new DataCube({
            ohlcv: data,
            onchart: [
              {
                type: 'BB', name: 'BBL', data: [],             
                settings: { lineWidth: false, color: false, backColor: false, showMid: true }
              },
              {
                type: 'EMA',name: 'EMA', data: [],
                settings: {color: "#f7890c", length: 12}
              }
            ],
            offchart: [
              {
                name: "MACD", type: "MACD", data: [],
              },
              {
                type: 'RSI', name: 'RSI', data: [],
                settings: {}
              }
            ]
          })
IlyaShkurenko commented 3 years ago

You can find the how-to in docs, but it's cleary shown on tests/examples. It's simple:

import Overlays from 'tvjs-overlays'

data() {
...
    overlays: [
            Overlays['EMA'], 
            Overlays['BB'], 
            Overlays['MACD'],
            Overlays['RSI']
     ]
      <trading-vue 
      ...
      :overlays="overlays" 
this.chart = new DataCube({
            ohlcv: data,
            onchart: [
              {
                type: 'BB', name: 'BBL', data: [],             
                settings: { lineWidth: false, color: false, backColor: false, showMid: true }
              },
              {
                type: 'EMA',name: 'EMA', data: [],
                settings: {color: "#f7890c", length: 12}
              }
            ],
            offchart: [
              {
                name: "MACD", type: "MACD", data: [],
              },
              {
                type: 'RSI', name: 'RSI', data: [],
                settings: {}
              }
            ]
          })

Got it, but still not clear few moments: 1) If I will do like you suggest can I access calculated points? Seems for this I should rewrite overlay. I need analyze all calculated points of special overlay and then draw my signals so not sure which methods needs to call. 2) Another option it's to pass already calculated data of indicator to overlay, had success for it with RSI and SMA, but not with Stoch. I've tried to to like this but it doesn't work; 3) for what is DataCube constructor?

const stochasticData = [{
k: 22.233633946283316, d: 40.85086679593228},
{k: 8.203779000238802,d:26.116909708452596}
{k: 30.026590880312483, d: 20.154667942278195}
{k: 32.778909725975794, d: 23.669759868842352}
{k: 43.81332557140256, d: 35.53960872589693}
{k: 13.113504373016264, d: 29.9019132234648]
 {
      "name": "Stoch",
      "type": "Stoch",
      "data": stochasticData.map(i => [i.k, i.d]),
      "settings": {
        upper: 80,
        lower: 20
      }
}

Thanks for help

Seungwoo321 commented 2 years ago

"data": stochasticData.map(i => [i.k, i.d]),

I'm guessing you'll need a timestamp to map to the x-axis.

original code: https://github.com/tvjsx/tvjs-overlays/blob/master/src/overlays/Stoch/Stoch.vue#L38

I've made some customizations.

import { Overlay } from 'trading-vue-js'
export default {
  name: 'Stochastic',
  mixins: [
    Overlay
  ],
  computed: {
    lineWidth () {
      return this.settings.lineWidth || 0.75
    },
    kWidth () {
      return this.settings.kWidth || this.lineWidth
    },
    dWidth () {
      return this.settings.dWidth || this.lineWidth
    },
    kColor () {
      return this.settings.kColor || '#0915f4'
    },
    dColor () {
      return this.settings.dColor || '#f43409'
    },
    bandColor () {
      return this.settings.bandColor || '#b5b3b3'
    },
    backColor () {
      // return this.settings.backColor || '#381e9c16'
      return 'rgba(182, 178, 184, 0.1)'
    }
  },
  methods: {
    meta_info () {
      return {
        author: 'StdSquad',
        version: '1.0.1',
        desc: this.desc
      }
    },
    draw (ctx) {
      const layout = this.$props.layout
      const upper = layout.$2screen(this.settings.upper || 80)
      const lower = layout.$2screen(this.settings.lower || 20)
      // K
      ctx.lineWidth = this.kWidth
      ctx.strokeStyle = this.kColor
      ctx.beginPath()
      for (const p of this.$props.data) {
        const x = layout.t2screen(p[0])
        const y = layout.$2screen(p[1])
        ctx.lineTo(x, y)
      }
      ctx.stroke()
      // D
      ctx.lineWidth = this.dWidth
      ctx.strokeStyle = this.dColor
      ctx.beginPath()
      for (const p of this.$props.data) {
        const x = layout.t2screen(p[0])
        const y = layout.$2screen(p[2])
        ctx.lineTo(x, y)
      }
      ctx.stroke()
      ctx.strokeStyle = this.bandColor
      ctx.setLineDash([5]) // Will be removed after draw()
      ctx.beginPath()
      // Fill the area between the bands
      ctx.fillStyle = this.backColor
      ctx.fillRect(0, upper, layout.width, lower - upper)
      // Upper band
      ctx.moveTo(0, upper)
      ctx.lineTo(layout.width, upper)
      // Lower band
      ctx.moveTo(0, lower)
      ctx.lineTo(layout.width, lower)
      ctx.stroke()
    },
    use_for () {
      return ['Stochastic']
    },
    data_colors () {
      return [this.color]
    },
    y_range (hi, lo) {
      return [
        Math.max(hi, this.settings.upper || 80),
        Math.min(lo, this.settings.lower || 20)
      ]
    },
    calc () {
      return {
        props: {
          type: {
            def: 'slow'
          },
          hiddenK: {
            def: false
          },
          hiddenD: {
            def: false
          },
          k: {
            def: 5,
            text: '%K'
          },
          d: {
            def: 3,
            text: '%D'
          },
          smooth: {
            def: 3,
            text: 'Smooth'
          }
        },
        update: `
          const fast_k_array = stoch(close, high, low, k, 'stoch')
          const fast_d_array = sma(fast_k_array, d, 'sma')
          if (type === "slow") {
            const slow_k = !hiddenK ? sma(fast_k_array, smooth, fast_k_array._id)[0] : undefined
            const slow_d = !hiddenD ? sma(fast_d_array, smooth, fast_d_array._id)[0] : undefined
            return [slow_k, slow_d]
          } else {
            return [!hiddenK ? fast_k_array[0] : undefined, !hiddenD ? fast_d_array[0] : undefined]
          }
        `
      }
    }
  }
}