/ Plotting / src / inds.jl
inds.jl
  1  # using BasicBSpline
  2  # function _smooth(arr)
  3  #     # Linear open B-spline space
  4  #     xs = 1:size(arr, 1)
  5  #     fs = arr
  6  #     p = 1
  7  #     k = KnotVector(xs) + KnotVector([xs[1], xs[end]])
  8  #     P = BSplineSpace{p}(k)
  9  #     # Compute the interpolant function (1-dim B-spline manifold)
 10  #     xs, BSplineManifold(fs, P).controlpoints
 11  # end
 12  
 13  function _check_size(subject, to)
 14      @assert subject == to "Indicator ($subject) should Match ohlcv data length ($to)."
 15  end
 16  _ncandles(fig) = length(plots(fig.content[1])[1][1][])
 17  _candle_str(::Nothing, n) = ""
 18  _candle_str(df, n) = candle_str(df[n, :])
 19  
 20  @doc """ Adds line indicators to a given figure.
 21  
 22  $(TYPEDSIGNATURES)
 23  
 24  The function `line_indicator!` takes a `Figure` object and one or more line data arrays as arguments.
 25  It first checks if the size of each line matches the number of candles in the figure.
 26  Then, it creates a new axis in the figure and links it with the price axis.
 27  For each line, it generates a random color and adds a line plot to the axis with a tooltip showing the value of the line at each point.
 28  """
 29  function line_indicator!(fig::Figure, lines...; df=nothing)
 30      for l in lines
 31          _check_size(size(l, 1), _ncandles(fig))
 32      end
 33      ax = axis!(fig)
 34      deregister_interactions!(ax, ())
 35      linkaxes!(_price_ax(fig), ax)
 36      function drawline!(n, line)
 37          str_func(n) = """Value: $(cn(line[n]))\n$(_candle_str(df, n))"""
 38          lines!(
 39              ax,
 40              line;
 41              color=RGBf(rand(seed!(n), 3)...),
 42              inspector_hover=make_tooltip_func(line, str_func),
 43          )
 44      end
 45      for (n, line) in enumerate(lines)
 46          drawline!(n, line)
 47      end
 48  end
 49  
 50  @doc """ Creates a figure with line indicators from a DataFrame.
 51  
 52  $(TYPEDSIGNATURES)
 53  
 54  The function `line_indicator` takes an `AbstractDataFrame` and one or more line data arrays as arguments.
 55  It first creates a figure using the `ohlcv` function with the DataFrame.
 56  Then, it calls the `line_indicator!` function to add line indicators to the figure.
 57  The function returns the figure with the added line indicators.
 58  """
 59  function line_indicator(df::AbstractDataFrame, lines...)
 60      fig = ohlcv(df)
 61      line_indicator!(fig, lines...; df)
 62      fig
 63  end
 64  
 65  @doc """ Adds channel indicators to a given figure.
 66  
 67  $(TYPEDSIGNATURES)
 68  
 69  The function `channel_indicator!` takes a `Figure` object and one or more line data arrays as arguments.
 70  It first checks if the size of each line matches the number of candles in the figure.
 71  Then, it creates a new axis in the figure and links it with the price axis.
 72  For each pair of lines, it generates a random color and adds a band plot to the axis with a tooltip showing the values of the upper and lower bounds at each point.
 73  The opacity of the band can be adjusted with the `opacity` keyword argument.
 74  """
 75  function channel_indicator!(fig::Figure, lines...; df=nothing, opacity=0.25)
 76      for l in lines
 77          _check_size(size(l, 1), _ncandles(fig))
 78      end
 79      ax = axis!(fig)
 80      deregister_interactions!(ax, ())
 81      linkaxes!(_price_ax(fig), ax)
 82  
 83      function drawband!(lower, upper, n, ylower, yupper)
 84          str_func(n) = """Upper: $(cn(yupper[n]))
 85          Lower: $(cn(ylower[n]))
 86          $(_candle_str(df, n))"""
 87          band!(
 88              ax,
 89              lower,
 90              upper;
 91              color=RGBAf(rand(seed!(n), 3)..., opacity),
 92              inspector_hover=make_tooltip_func(ylower, str_func),
 93          )
 94      end
 95      points(line) = [Point2f(x, y) for (x, y) in enumerate(line)]
 96      lower, upper = points.(first(lines, 2))
 97      n = 0
 98      drawband!(lower, upper, n, first(lines, 2)...)
 99      if length(lines) > 2
100          n += 1
101          prevline = lines[2]
102          for line in lines[3:end]
103              lower = upper
104              upper = points(line)
105              drawband!(lower, upper, n, prevline, line)
106              prevline = line
107          end
108      end
109  end
110  
111  @doc """ Adds channel indicators to a given figure.
112  
113  $(TYPEDSIGNATURES)
114  
115  The function `channel_indicator!` takes a `Figure` object and one or more line data arrays as arguments.
116  It first checks if the size of each line matches the number of candles in the figure.
117  Then, it creates a new axis in the figure and links it with the price axis.
118  For each pair of lines, it generates a random color and adds a band plot to the axis with a tooltip showing the values of the upper and lower bounds at each point.
119  The opacity of the band can be adjusted with the `opacity` keyword argument.
120  """
121  function channel_indicator(df::AbstractDataFrame, lines...; opacity=0.25)
122      fig = ohlcv(df)
123      channel_indicator!(fig, lines...; opacity, df)
124      fig
125  end
126  
127  channel_indicator(df, lines::AbstractVector) = channel_indicator(df, lines...)
128  channel_indicator!(fig, lines::AbstractVector) = channel_indicator!(fig, lines...)
129  
130  export line_indicator, line_indicator!, channel_indicator, channel_indicator!