ramnathv / rCharts

Interactive JS Charts from R
http://rcharts.io
Other
1.19k stars 654 forks source link

candlestick chart with volume chart and range selector using highcharts? #320

Open Arbitrageur opened 10 years ago

Arbitrageur commented 10 years ago

Could you give me an example?

I'm not sure that this is the right place for asking.. but thanks anyway.

ramnathv commented 10 years ago

If you can find an example implemented in javascript, I can investigate how you might do the same from R using rCharts.

Arbitrageur commented 10 years ago

Here's an example from highcharts.com

Happy new year!

$(function() {
    $.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-ohlcv.json&callback=?', function(data) {

        // split the data set into ohlc and volume
        var ohlc = [],
            volume = [],
            dataLength = data.length;

        for (i = 0; i < dataLength; i++) {
            ohlc.push([
                data[i][0], // the date
                data[i][1], // open
                data[i][2], // high
                data[i][3], // low
                data[i][4] // close
            ]);

            volume.push([
                data[i][0], // the date
                data[i][5] // the volume
            ])
        }

        // set the allowed units for data grouping
        var groupingUnits = [[
            'week',                         // unit name
            [1]                             // allowed multiples
        ], [
            'month',
            [1, 2, 3, 4, 6]
        ]];

        // create the chart
        $('#container').highcharts('StockChart', {

            rangeSelector: {
                selected: 1
            },

            title: {
                text: 'AAPL Historical'
            },

            yAxis: [{
                title: {
                    text: 'OHLC'
                },
                height: 200,
                lineWidth: 2
            }, {
                title: {
                    text: 'Volume'
                },
                top: 300,
                height: 100,
                offset: 0,
                lineWidth: 2
            }],

            series: [{
                type: 'candlestick',
                name: 'AAPL',
                data: ohlc,
                dataGrouping: {
                    units: groupingUnits
                }
            }, {
                type: 'column',
                name: 'Volume',
                data: volume,
                yAxis: 1,
                dataGrouping: {
                    units: groupingUnits
                }
            }]
        });
    });
});
ramnathv commented 10 years ago

I will check how this can be achieved using the rCharts binding. Meanwhile, here is an example of a candlestick chart with range selector using eCharts. echarts is not yet in the main branch of rCharts, so you will have to download the echarts binding and make sure that you refer to its correct path in the setLib step in the code I linked to earlier.

echarts-candle

nemonominem commented 10 years ago

Ramanth, do you have any plan to support Highstock (http://www.highcharts.com/stock/demo/candlestick) in rCharts?

With a quick hack (copying rCharts highchart library into a custom hightock libray, modifying the config.yml and a few files there), I could to get highstock to work within rCharts and I am now trying to reproduce some of the Highstock examples. In particular the candlestick graphs work fine (to answer Arbitrageur's exact request, one can also easily add a volume graph to the candlestick graphs).

capture

One problem I have is that Highstock is supposed to include Highcharts in itself (it's a superset of functionnalities), so it seems a bit redundant to support both highcharts and highstock under rCharts. I am doing a few tests but so far it seems I can altogether drop the rCharts Highcharts library in my custom build and avoid any possible conflict down the line.

For info: The data format expected by Highstock is straightforward. Here is an example:

require(rCharts)
require(quantmod)  #Load the quantmod Library

startDate <- as.Date("2010-01-01") #Specify period of time we are interested in
endDate   <- as.Date("2013-12-31")

tickers   <- c('AAPL', 'MSFT', 'MMM', 'V', 'HD', 'GE') #Define the tickers we are interested in
getSymbols(tickers, src = "google", from = startDate, to = endDate)

processQuantmodOHLC = function(name)
{
    tmp           <- OHLC(get(name))
    colnames(tmp) <- c('Open','High', 'Low', 'Close')

    stock         <- data.frame(t=index(tmp), coredata(tmp)) 
    stock$date    <- as.numeric(as.POSIXct(stock$t, origin="1970-01-01")) * 1000
    stock$stock   <- name

    return( stock )
}

stocks  <- do.call(rbind, lapply(tickers, processQuantmodOHLC))

aapl    <- subset(stocks, stock=='AAPL')
ohlcPlot(data = aapl, title='AAPL')

with:

ohlcPlot <- highstockOHLC <- function(name='a stock', data=data, radius = 3, title = NULL, subtitle = NULL)
{
    rChart <- Highstock$new()

    nrows <- nrow(data)
    data  <- na.omit(data) # remove remaining observations with NA's

    if (nrows != nrow(data))
        warning("Observations with NA has been removed")  

    rChart$series(
        data = toJSONArray2(data[c('date', 'Open', 'High', 'Low', 'Close')], json = F, names = F),
        type = 'candlestick',
        name = name,
        marker = list(radius = radius))

    rChart$legend(enabled = FALSE)

    ## title
    rChart$title(text = title, replace = T)

    ## subtitle
    rChart$subtitle(text = subtitle, replace = T)

    return(rChart$copy())
}

and with Hightstock being just a direct translation of the rChart code for Highcharts:

Highstock <- setRefClass("Highstock", contains = "rCharts", methods = list(
initialize = function()
{
    callSuper(); lib <<- 'highstock'; LIB <<- get_lib(lib)

    params <<- c(params, list(
                            credits = list(href = NULL, text = NULL),
                            exporting = list(enabled = F),
                            title = list(text = NULL),
                            yAxis = list(title = list(text = NULL))
                        ))
},

getPayload = function(chartId){

    # Set params before rendering
    params$chart$renderTo <<- chartId

    list(chartParams = toJSON2(params, digits = 13), chartId = chartId)
},

#' Wrapper methods
chart = function(..., replace = T)
{
    params$chart <<- setSpec(params$chart, ..., replace = replace)
},

colors = function(..., replace = T)
{
    args <- unlist(list(...))

    if (replace) {
        params$colors <<- args
    } else {
        params$colors <<- c(params$colors, args)
    }
},

credits = function(..., replace = T){
    params$credits <<- setSpec(params$credits, ..., replace = replace)
},

exporting = function(..., replace = T){
    params$exporting <<- setSpec(params$exporting, ..., replace = replace)
},

global = function(..., replace = T){
    params$global <<- setSpec(params$global, ..., replace = replace)
},

labels = function(..., replace = T){
    params$labels <<- setSpec(params$labels, ..., replace = replace)
},

lang = function(..., replace = T){
    params$lang <<- setSpec(params$lang, ..., replace = replace)
},

legend = function(..., replace = T){
    params$legend <<- setSpec(params$legend, ..., replace = replace)
},

loading = function(..., replace = T){
    params$loading <<- setSpec(params$loading, ..., replace = replace)
},

navigation = function(..., replace = T){
    params$navigation <<- setSpec(params$navigation, ..., replace = replace)
},

pane = function(..., replace = T){
    params$pane <<- setSpec(params$pane, ..., replace = replace)
},

plotOptions = function(..., replace = T){
    params$plotOptions <<- setSpec(params$plotOptions, ..., replace = replace)
},

series = function(..., replace = F) {
    params$series <<- setListSpec(params$series, ..., replace = replace)
},

subtitle = function(..., replace = T){
    params$subtitle <<- setSpec(params$subtitle, ..., replace = replace)
},

title = function(..., replace = T){
    params$title <<- setSpec(params$title, ..., replace = replace)
},

tooltip = function(..., replace = T){
    params$tooltip <<- setSpec(params$tooltip, ..., replace = replace)
},

xAxis = function(..., replace = T) {
    params$xAxis <<- setListSpec(params$xAxis, ..., replace = replace)
},

yAxis = function(..., replace = T) {
    params$yAxis <<- setListSpec(params$yAxis, ..., replace = replace)
},

# Custom add data method
data = function(x = NULL, y = NULL, ...)
{
    if (is.data.frame(x))
    {
        for (i in colnames(x))
        {
            if (is.numeric(x[[i]]))
                series(name = i, data = x[[i]], ...)
            else
                warning (sprintf("Column '%s' wasn't added since it's not a numeric", i))
        }
    } else
    {
        if (is.null(y) || !is.numeric(y))
            series(data = x, ...)
        else
        {
            if (length(x) != length(y))
                stop ("Arguments x and y must be of the same length")

            xy <- lapply(1:length(x), function(i) list(x[i], y[i]))
            series(data = xy, ...)
        }
    }
}))
ramnathv commented 10 years ago

This is cool. Can you post your highstock library folder on github, so that I can see what changes are required when compared to highcharts? If it is only about extra js/css assets, there might be a way to absorb things into the highcharts library itself, especially since the R code for the class seems to be exactly identical.

nemonominem commented 10 years ago

You can see my quick go at of a highstock library on https://github.com/nemonominem/Highstock-rCharts-hack. The files under the 'hack' directory are standalone for the time being (I have not tried to rebuild the rCharts package). Otherwise it is just some changes in the js libraries and in the config.yml, and also in the layout chart.html (to call the right constructor). This should be able to support both Highchart and Highstock functionalities. The https://github.com/nemonominem/Highstock-rCharts-hack/blob/master/highstock/examples_highstock.R file is still rudimentary but it shows that it can work. capture1

nemonominem commented 10 years ago

It looks like one may have to have some separate Highcharts and Highstock R objects as the methods and default behaviors are slightly different.

Per http://api.highcharts.com/highstock and http://api.highcharts.com/highcharts:

As an example of slightly different behavior, legend is enabled by default in Highcharts and not enabled in Highstock. I suspect a few subtle minor differences like that.

One may also want to change the data() method of the Highstock object to reflect the more specific data series usage. I have not bothered with that yet.

Then one can simply add an sPlot wrapper function and maybe some ohlcPlot wrapper function too (or alternatively one could create a dedicated R object inheriting from Highstock for OHLC).

This could all be packed in a revised highchart library under rCharts.

ramnathv commented 10 years ago

This is looking really good! Let me spend some time this weekend going over your code and trying to figure out if it makes most sense to roll this into the highcharts library or create a separate highstock library.

ramnathv commented 10 years ago

I apologise for not getting back on this. I have been really busy with stuff. I will certainly take a closer look at this in the next couple of weeks and figure out the best way to add highstocks bindings.

smbache commented 10 years ago

Any progress on this? I'll add myself to the list of interested individuals :)

asosnovsky commented 10 years ago

For all of those who don't feel like diving into the magical world of rCharts. I created a simple package based on ramnathv and nemonominem code. Here is the package, you will have to download and install it manually (I don't want to upload it to github, since its not my original all the credit belongs to those guys and those guys only!) Here is the link: https://mega.co.nz/#!kRJggTrK!NsGz1AWcFZxfRrfNCsm2sXR8F0mCzGbD917Ebjatie8

Just download it and manually install the package in R. sPlot and highstock should work well! (It will simply update the rCharts package with the Highstocks library)

ramnathv commented 10 years ago

@Vapri Thanks for your efforts in doing this. I was thinking more along the lines of creating a sister package rChartsHighstocks that would import rCharts as a dependency. This would allow you to maintain rChartsHighstocks independent of rCharts and not having to rewrite it. If you are interested, I can help set it up. Maybe @nemonominem will also be interested in this.

asosnovsky commented 10 years ago

yea sure, I am willing to help if you want to.

asosnovsky commented 10 years ago

email me at Ariel_vps@live.com

danielkrizian commented 10 years ago

Please note, that this is planned feature of dygraph library in the near future: https://github.com/danielkrizian/dygraphs/issues?state=open

I did research couple of months ago when looking for interactive time-series charting library, also compared highcharts vs dygraphs and settled for dygraphs for three reasons: friendlier licencing, fully open-sourced and speed (direct rendering on canvas, instead of SVG, which might get bogged down on dense datasets)

Plugins introduced recently include arrow annotations with popups (trading orders) and synchronized charts with crosshair (for multiple indicators): http://rawgit.com/danielkrizian/dygraphs/master/tests/canvas-annotation-synchronize-series.html http://rawgit.com/danielkrizian/rCharts_dygraphs/master/examples/multi-layout.html

Working R wrapper here (thank you @ramnathv & @timelyportfolio for indispensable kickstart advice): https://github.com/danielkrizian/rCharts_dygraphs

If you decide to jump on the dygraphs bandwagon, let me know (danielDOTkrizianATgmail)

ramnathv commented 10 years ago

I would agree with @danielkrizian that dygraphs is a great choice due to speed and friendlier licensing. @danielkrizian has done some awesome work and I look forward to more people using the rChartsDygraph library as it develops.

ramnathv commented 10 years ago

@Vapri I will send you an email and copy to @nemonominem as well so you guys can get together to discuss the best way to put a rChartsHighStock package in place.

asosnovsky commented 10 years ago

Very excited for Dygraph, looks very nice. I'd still want to make Highstock as a package though, already started working on it. Though I wouldn't mind lending a hand on Dygraph. It looks like it has lots of potential.

ramnathv commented 10 years ago

I agree @Vapri that it makes sense to develop both packages. Highstocks is very refined, with cost probably being the only barrier. But then again, given that it is in the finance domain, cost may not be an issue for many firms.

danielkrizian commented 10 years ago

Candlestick chart is now implemented in dygraphs, thanks to @pshevtsov

Demo here: http://rawgit.com/danielkrizian/dygraphs/candlestick/tests/candlestick.html

Issue tracker if you are interested in tweaking it: https://github.com/danielkrizian/dygraphs/issues/11#issuecomment-44247496

ctrlbrk42 commented 10 years ago

I want to ask if @ramnathv has made progress on making a Highstock library. I just stumbled on Highstock today, and it is exactly what I need and have been trying to make Highcharts do. So instead of re-inventing the wheel, I am now looking for an R library for Highstock.

ramnathv commented 10 years ago

I don't have the bandwidth to focus on Highstock. If someone is interested in consolidating the Highstock efforts so far and create a highstocks binding, I would be happy to help and add it to rCharts.

ctrlbrk42 commented 10 years ago

I am willing to kick in some $$ in a crowdsourced fundraiser if it will help to get this done.

timelyportfolio commented 10 years ago

I would suggest having a peek at rChartsDygraphs . He has been doing a great job and has also kicked in some $ for help on the js side.

ramnathv commented 10 years ago

I think most of the work to integrate highstock has already been done.

https://github.com/Vapri/rChartsHighStockMod https://github.com/nemonominem/Highstock-rCharts-hack

At this point, I believe it only requires to be cleaned up, documented and packaged appropriately. If anyone is interested, let me know.

ctrlbrk42 commented 10 years ago

dygraphs looks good but I would rather stick with rCharts only because I am very familiar with Highcharts at this point, and assume Highstocks to be very similar. I do not have the skills to "clean up and package appropriately", so must rely on others to do this. I can only contribute $$$ to help expedite.

KrysD commented 8 years ago

Hi, I'm really interested by the work done to use Highstock library in rCharts. is-it implemented for now in rCharts or did I need to use the hack standalone code ?

danielkrizian commented 8 years ago

@KrysD, rCharts project has been abandoned and its main ideas restructured into www.htmlwidgets.org project AFAIK. Concerning candlesticks, R porting of dygraphs is now the actively maintained and developed route and implements the interactive time series charting on top of htmlwidgets plumbing. Candlestick add-in under development is here

KrysD commented 8 years ago

O sad news ! Thank's @danielkrizian , i will take a look

ramnathv commented 8 years ago

@danielkrizian rCharts has not been abandoned. The ideas were ported to htmlwidgets to make a generic framework that would support creating javascript based widgets. I am in the process porting rCharts to the htmlwidgets framework and once that is complete, all functionality in rCharts will be available there and continue to be developed there.

ramnathv commented 8 years ago

@KrysD once I port rCharts, I will take a look at the highstock implementation. It should not be hard adding it to what is already out there currently.

KrysD commented 8 years ago

@ramnathv, it means I could continue to use rCharts nice !!!

jbkunst commented 8 years ago

Hi everyone, @KrysD ,

If anyone still interested in highstock funcionalities you can check highcharter package.

Regards

screenshot_1

KrysD commented 8 years ago

Hi @jbkunst ,
i will check this, it look interesting.

yash27 commented 6 years ago

Hi @Arbitrageur , can you please help me in making that candlestick highchart dynamic.

$(function() {
    $.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-ohlcv.json&callback=?', function(data) {
        // split the data set into ohlc and volume
        var ohlc = [],
            volume = [],
            dataLength = data.length;

        for (i = 0; i < dataLength; i++) {
            ohlc.push([
                data[i][0], // the date
                data[i][1], // open
                data[i][2], // high
                data[i][3], // low
                data[i][4] // close
            ]);

            volume.push([
                data[i][0], // the date
                data[i][5] // the volume
            ])
        }

        // set the allowed units for data grouping
        var groupingUnits = [[
            'week',                         // unit name
            [1]                             // allowed multiples
        ], [
            'month',
            [1, 2, 3, 4, 6]
        ]];

        // create the chart
        $('#container').highcharts('StockChart', {

            rangeSelector: {
                selected: 1
            },

            title: {
                text: 'AAPL Historical'
            },

            yAxis: [{
                title: {
                    text: 'OHLC'
                },
                height: 200,
                lineWidth: 2
            }, {
                title: {
                    text: 'Volume'
                },
                top: 300,
                height: 100,
                offset: 0,
                lineWidth: 2
            }],

            series: [{
                type: 'candlestick',
                name: 'AAPL',
                data: ohlc,
                dataGrouping: {
                    units: groupingUnits
                }
            }, {
                type: 'column',
                name: 'Volume',
                data: volume,
                yAxis: 1,
                dataGrouping: {
                    units: groupingUnits
                }
            }]
        });
    });
});

Dynamic in the sense that whatever data we're getting from the JSON file, that should come one by one after every second and using splice technique also we should remove the first data.