ohlc recipe and related fixes; removed ohlc-specific code from gadfly and gr
This commit is contained in:
parent
89feb68b7c
commit
333c2765fe
@ -10,7 +10,7 @@ const _allAxes = [:auto, :left, :right]
|
||||
const _3dTypes = [:path3d, :scatter3d, :surface, :wireframe, :contour3d]
|
||||
const _allTypes = vcat([
|
||||
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
|
||||
:heatmap, :hexbin, :hist, :hist2d, :hist3d, :density, :bar, :hline, :vline, :ohlc,
|
||||
:heatmap, :hexbin, :hist, :hist2d, :hist3d, :density, :bar, :hline, :vline, #:ohlc,
|
||||
:contour, :pie, :shape, :image #, :boxplot, :violin, :quiver,
|
||||
], _3dTypes)
|
||||
@compat const _typeAliases = KW(
|
||||
|
||||
@ -298,9 +298,9 @@ function addGadflySeries!(plt::Plot, d::KW)
|
||||
|
||||
# special handling for ohlc and scatter
|
||||
st = d[:seriestype]
|
||||
if st == :ohlc
|
||||
error("Haven't re-implemented after refactoring")
|
||||
elseif st in (:hist2d, :hexbin) && (isa(d[:fillcolor], ColorGradient) || isa(d[:fillcolor], ColorFunction))
|
||||
# if st == :ohlc
|
||||
# error("Haven't re-implemented after refactoring")
|
||||
if st in (:hist2d, :hexbin) && (isa(d[:fillcolor], ColorGradient) || isa(d[:fillcolor], ColorFunction))
|
||||
push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:fillcolor], p))))
|
||||
elseif st == :scatter && d[:markershape] == :none
|
||||
d[:markershape] = :ellipse
|
||||
|
||||
@ -40,7 +40,7 @@ supportedTypes(::GRBackend) = [
|
||||
:none, :line, :path, :steppre, :steppost,
|
||||
:scatter, :hist2d, :hexbin, :hist, :density,
|
||||
:bar, :sticks,
|
||||
:hline, :vline, :heatmap, :pie, :image, :ohlc,
|
||||
:hline, :vline, :heatmap, :pie, :image, #:ohlc,
|
||||
:contour, :path3d, :scatter3d, :surface, :wireframe
|
||||
]
|
||||
supportedStyles(::GRBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||
@ -261,8 +261,8 @@ function gr_display(plt::Plot{GRBackend}, clear=true, update=true,
|
||||
end
|
||||
if st == :bar
|
||||
x, y = 1:length(p[:y]), p[:y]
|
||||
elseif st == :ohlc
|
||||
x, y = 1:size(p[:y], 1), p[:y]
|
||||
# elseif st == :ohlc
|
||||
# x, y = 1:size(p[:y], 1), p[:y]
|
||||
elseif st in [:hist, :density]
|
||||
x, y = Base.hist(p[:y], p[:bins])
|
||||
elseif st in [:hist2d, :hexbin]
|
||||
@ -295,15 +295,15 @@ function gr_display(plt::Plot{GRBackend}, clear=true, update=true,
|
||||
if !(st in [:pie, :polar])
|
||||
xmin = min(minimum(x), xmin)
|
||||
xmax = max(maximum(x), xmax)
|
||||
if st == :ohlc
|
||||
for val in y
|
||||
ymin = min(val.open, val.high, val.low, val.close, ymin)
|
||||
ymax = max(val.open, val.high, val.low, val.close, ymax)
|
||||
end
|
||||
else
|
||||
# if st == :ohlc
|
||||
# for val in y
|
||||
# ymin = min(val.open, val.high, val.low, val.close, ymin)
|
||||
# ymax = max(val.open, val.high, val.low, val.close, ymax)
|
||||
# end
|
||||
# else
|
||||
ymin = min(minimum(y), ymin)
|
||||
ymax = max(maximum(y), ymax)
|
||||
end
|
||||
# end
|
||||
if p[:xerror] != nothing || p[:yerror] != nothing
|
||||
dx = xmax - xmin
|
||||
xmin -= 0.02 * dx
|
||||
@ -460,7 +460,7 @@ function gr_display(plt::Plot{GRBackend}, clear=true, update=true,
|
||||
GR.savestate()
|
||||
xmin, xmax, ymin, ymax = extrema[gr_getaxisind(p),:]
|
||||
GR.setwindow(xmin, xmax, ymin, ymax)
|
||||
if st in [:path, :line, :steppre, :steppost, :sticks, :hline, :vline, :ohlc, :polar]
|
||||
if st in [:path, :line, :steppre, :steppost, :sticks, :hline, :vline, :polar] # :ohlc, :polar]
|
||||
GR.setlinetype(gr_linetype[p[:linestyle]])
|
||||
GR.setlinewidth(p[:linewidth])
|
||||
GR.setlinecolorind(gr_getcolorind(p[:linecolor]))
|
||||
@ -675,15 +675,15 @@ function gr_display(plt::Plot{GRBackend}, clear=true, update=true,
|
||||
GR.setcharheight(charheight)
|
||||
GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize)
|
||||
GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize)
|
||||
elseif st == :ohlc
|
||||
y = p[:y]
|
||||
n = size(y, 1)
|
||||
ticksize = 0.5 * (xmax - xmin) / n
|
||||
for i in 1:n
|
||||
GR.polyline([i-ticksize, i], [y[i].open, y[i].open])
|
||||
GR.polyline([i, i], [y[i].low, y[i].high])
|
||||
GR.polyline([i, i+ticksize], [y[i].close, y[i].close])
|
||||
end
|
||||
# elseif st == :ohlc
|
||||
# y = p[:y]
|
||||
# n = size(y, 1)
|
||||
# ticksize = 0.5 * (xmax - xmin) / n
|
||||
# for i in 1:n
|
||||
# GR.polyline([i-ticksize, i], [y[i].open, y[i].open])
|
||||
# GR.polyline([i, i], [y[i].low, y[i].high])
|
||||
# GR.polyline([i, i+ticksize], [y[i].close, y[i].close])
|
||||
# end
|
||||
elseif st == :pie
|
||||
GR.selntran(0)
|
||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||
|
||||
@ -374,15 +374,6 @@ end
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
type OHLC{T<:Real}
|
||||
open::T
|
||||
high::T
|
||||
low::T
|
||||
close::T
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# style is :open or :closed (for now)
|
||||
immutable Arrow
|
||||
style::Symbol
|
||||
|
||||
@ -197,6 +197,12 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
next_series = pop!(still_to_process)
|
||||
series_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
|
||||
for series in series_list
|
||||
|
||||
# series should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
|
||||
if !(typeof(series) <: RecipeData)
|
||||
error("Inputs couldn't be processed... expected RecipeData but got: $series")
|
||||
end
|
||||
|
||||
# @show series
|
||||
if isempty(series.args)
|
||||
# when the arg tuple is empty, that means there's nothing left to recursively
|
||||
|
||||
@ -20,7 +20,7 @@ num_series(x) = 1
|
||||
# _apply_recipe(d::KW, kw::KW) = ()
|
||||
|
||||
# if it's not a recipe, just do nothing and return the args
|
||||
function RecipesBase.apply_recipe(d::KW, kw::KW, args...; issubplot=false)
|
||||
function RecipesBase.apply_recipe(d::KW, args...; issubplot=false)
|
||||
if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout)
|
||||
# put in a sensible default
|
||||
d[:n] = maximum(map(num_series, args))
|
||||
@ -540,7 +540,65 @@ function getRecipeArgs(ep::EllipseRecipe)
|
||||
[(:line, (3, [:dot :solid], [:red :blue], :path))]
|
||||
end
|
||||
|
||||
# # -------------------------------------------------
|
||||
# -------------------------------------------------
|
||||
|
||||
# TODO: this should really be in another package...
|
||||
type OHLC{T<:Real}
|
||||
open::T
|
||||
high::T
|
||||
low::T
|
||||
close::T
|
||||
end
|
||||
tuple(ohlc::OHLC) = (ohlc.open, ohlc.high, ohlc.low, ohlc.close)
|
||||
|
||||
# get one OHLC path
|
||||
function get_xy(o::OHLC, x, xdiff)
|
||||
xl, xm, xr = x-xdiff, x, x+xdiff
|
||||
ox = [xl, xm, NaN,
|
||||
xm, xm, NaN,
|
||||
xm, xr]
|
||||
oy = [o.open, o.open, NaN,
|
||||
o.low, o.high, NaN,
|
||||
o.close, o.close]
|
||||
ox, oy
|
||||
end
|
||||
|
||||
# get the joined vector
|
||||
function get_xy(v::AVec{OHLC}, x = 1:length(v))
|
||||
xdiff = 0.3mean(abs(diff(x)))
|
||||
x_out, y_out = zeros(0), zeros(0)
|
||||
for (i,ohlc) in enumerate(v)
|
||||
ox,oy = get_xy(ohlc, x[i], xdiff)
|
||||
nanappend!(x_out, ox)
|
||||
nanappend!(y_out, oy)
|
||||
end
|
||||
x_out, y_out
|
||||
end
|
||||
|
||||
# these are for passing in a vector of OHLC objects
|
||||
# TODO: when I allow `@recipe f(::Type{T}, v::T) = ...` definitions to replace convertToAnyVector,
|
||||
# then I should replace these with one definition to convert to a vector of 4-tuples
|
||||
|
||||
# to squash ambiguity warnings...
|
||||
@recipe f(x::AVec{Function}, v::AVec{OHLC}) = error()
|
||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(x::AVec{Function}, v::AVec{Tuple{R1,R2,R3,R4}}) = error()
|
||||
|
||||
# this must be OHLC?
|
||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(x::AVec, ohlc::AVec{Tuple{R1,R2,R3,R4}}) = x, OHLC[OHLC(t...) for t in ohlc]
|
||||
|
||||
@recipe function f(x::AVec, v::AVec{OHLC})
|
||||
d[:seriestype] = :path
|
||||
get_xy(v, x)
|
||||
end
|
||||
|
||||
@recipe function f(v::AVec{OHLC})
|
||||
d[:seriestype] = :path
|
||||
get_xy(v)
|
||||
end
|
||||
|
||||
# the series recipe, when passed vectors of 4-tuples
|
||||
|
||||
# -------------------------------------------------
|
||||
|
||||
|
||||
"Sparsity plot... heatmap of non-zero values of a matrix"
|
||||
|
||||
@ -44,8 +44,8 @@ convertToAnyVector(f::Function, d::KW) = Any[f], nothing
|
||||
# surface
|
||||
convertToAnyVector(s::Surface, d::KW) = Any[s], nothing
|
||||
|
||||
# vector of OHLC
|
||||
convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
|
||||
# # vector of OHLC
|
||||
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
|
||||
|
||||
# dates
|
||||
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::KW) = Any[dts], nothing
|
||||
|
||||
@ -450,6 +450,11 @@ end
|
||||
@recipe f{R1<:Number,R2<:Number,R3<:Number}(xyz::AVec{Tuple{R1,R2,R3}}) = unzip(xyz)
|
||||
@recipe f{R1<:Number,R2<:Number,R3<:Number}(xyz::Tuple{R1,R2,R3}) = [xyz[1]], [xyz[2]], [xyz[3]]
|
||||
|
||||
# these might be points+velocity, or OHLC or something else
|
||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(xyuv::AVec{Tuple{R1,R2,R3,R4}}) = get(d,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
|
||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(xyuv::Tuple{R1,R2,R3,R4}) = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]]
|
||||
|
||||
|
||||
#
|
||||
# # 2D FixedSizeArrays
|
||||
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::AVec{FixedSizeArrays.Vec{2,T}})
|
||||
|
||||
14
src/utils.jl
14
src/utils.jl
@ -156,13 +156,19 @@ maketuple{T,S}(x::@compat(Tuple{T,S})) = x
|
||||
mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
|
||||
mapFuncOrFuncs(fs::AVec{Function}, u::AVec) = [map(f, u) for f in fs]
|
||||
|
||||
unzip{T,S}(xy::AVec{Tuple{T,S}}) = [x[1] for x in xy], [y[2] for y in xy]
|
||||
unzip{T,S,R}(xyz::AVec{Tuple{T,S,R}}) = [x[1] for x in xyz], [y[2] for y in xyz], [z[3] for z in xyz]
|
||||
unzip{T}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = T[x[1] for x in xy], T[y[2] for y in xy]
|
||||
unzip{X,Y}(xy::AVec{Tuple{X,Y}}) = [t[1] for t in xy], [t[2] for t in xy]
|
||||
unzip{X,Y,Z}(xyz::AVec{Tuple{X,Y,Z}}) = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
|
||||
unzip{X,Y,U,V}(xyuv::AVec{Tuple{X,Y,U,V}}) = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
|
||||
|
||||
unzip{T}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = T[t[1] for t in xy], T[t[2] for t in xy]
|
||||
unzip{T}(xy::FixedSizeArrays.Vec{2,T}) = T[xy[1]], T[xy[2]]
|
||||
unzip{T}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = T[x[1] for x in xyz], T[y[2] for y in xyz], T[z[3] for z in xyz]
|
||||
|
||||
unzip{T}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
|
||||
unzip{T}(xyz::FixedSizeArrays.Vec{3,T}) = T[xyz[1]], T[xyz[2]], T[xyz[3]]
|
||||
|
||||
unzip{T}(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
|
||||
unzip{T}(xyuv::FixedSizeArrays.Vec{4,T}) = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
|
||||
|
||||
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
||||
function _expand_limits(lims, x)
|
||||
try
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user