ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Finance Chart volume profile sample request (C#)
Posted by Brian Hui on Jan-12-2024 17:52
Attachments:
Hi Peter,

I just started to develop the volume profile in my finance chart. I tried to search in this support forum. However, it is no suitable sample for me. See whether you can provide a simple sample coding in C# for me. The finishing result should be look like the attached picture. Many thanks!

Regards,
Brian
volume profile.png

  Re: Finance Chart volume profile sample request (C#)
Posted by Peter Kwan on Jan-13-2024 03:57
Hi Brian Hui,

There is an example in this forum that I wrote a few years ago, but it is in C++ syntax:

https://www.chartdir.com/forum/download_thread.php?bn=chartdir_support&thread=1574568936#N1575274576

Please let me know if the above is what you need. If you need me to translate the code to C#, please let me know.

Regards,
Brian

  Re: Finance Chart volume profile sample request (C#)
Posted by Brian Hui on Jan-15-2024 21:43
Hi Peter,

Yes. It is quite difficult for me to translate the sample code from C++ to C#. It would be highly appreciated if you could help. Many thanks!

Regards,
Brian

  Re: Finance Chart volume profile sample request (C#)
Posted by Peter Kwan on Jan-16-2024 02:28
Attachments:
Hi Brian,

Below please find the code in C#. The code is modified from the "Finance Chart (1)" sample code. Basically, the code creates an additional horizontal bar chart and use it as the plot area background of the financial chart. The key is to how to position the horizontal bars correctly.



//==== Start of Code ====

using System;
using ChartDirector;

namespace CSharpChartExplorer
{
    public class finance : DemoModule
    {
        //Name of demo module
        public string getName() { return "Finance Chart (1)"; }

        //Number of charts produced in this demo module
        public int getNoOfCharts() { return 1; }

        BarLayer addPriceVolLayer(XYChart c, int startPos, int endPos, double[] priceDataX, double[] volDataY, int color)
        {
            BarLayer layer = c.addBarLayer(volDataY, color);
            layer.setBorderColor(Chart.SameAsMainColor);
            layer.setXData(priceDataX);
            layer.setBarGap(Chart.TouchBar);

            // Create a dedicated axis for this layer to allow us to control the bar
            // direction and position for this layer
            Axis a = c.addAxis(Chart.Bottom, 10);
            a.setAutoScale(0, 0, 1);
            a.setRounding(false, false);
            layer.setUseYAxis(a);

            // If endPos > startPos, reverse bar direction
            if (endPos > startPos)
            {
                a.setReverse();
                int temp = startPos;
                startPos = endPos;
                endPos = temp;
            }

            // Position the bars by manipulating the axis margin
            a.setMargin(c.getPlotArea().getWidth() - endPos, startPos);

            return layer;
        }

        public void createChart(WinChartViewer viewer, int chartIndex)
        {
            // Create a finance chart demo containing 100 days of data
            int noOfDays = 100;

            // To compute moving averages starting from the first day, we need to get extra data points
            // before the first day
            int extraDays = 30;

            // In this exammple, we use a random number generator utility to simulate the data. We set up
            // the random table to create 6 cols x (noOfDays + extraDays) rows, using 9 as the seed.
            RanTable rantable = new RanTable(9, 6, noOfDays + extraDays);

            // Set the 1st col to be the timeStamp, starting from Sep 4, 2002, with each row representing
            // one day, and counting week days only (jump over Sat and Sun)
            rantable.setDateCol(0, Chart.chartTime(2002, 9, 4), 86400, true);

            // Set the 2nd, 3rd, 4th and 5th columns to be high, low, open and close data. The open value
            // starts from 100, and the daily change is random from -5 to 5.
            rantable.setHLOCCols(1, 100, -5, 5);

            // Set the 6th column as the vol data from 5 to 25 million
            rantable.setCol(5, 50000000, 250000000);

            // Now we read the data from the table into arrays
            double[] timeStamps = rantable.getCol(0);
            double[] highData = rantable.getCol(1);
            double[] lowData = rantable.getCol(2);
            double[] openData = rantable.getCol(3);
            double[] closeData = rantable.getCol(4);
            double[] volData = rantable.getCol(5);

            // Create a FinanceChart object of width 640 pixels
            FinanceChart c = new FinanceChart(640);

            // Add a title to the chart
            c.addTitle("Finance Chart Demonstration");

            // Set the data into the finance chart object
            c.setData(timeStamps, highData, lowData, openData, closeData, volData, extraDays);

            // Add the main chart with 240 pixels in height
            XYChart mainChart = c.addMainChart(240);

            // Add a 5 period simple moving average to the main chart, using brown color
            c.addSimpleMovingAvg(5, 0x663300);

            // Add a 20 period simple moving average to the main chart, using purple color
            c.addSimpleMovingAvg(20, 0x9900ff);

            // Add HLOC symbols to the main chart, using green/red for up/down days
            c.addHLOC(0x008000, 0xcc0000);

            // Add 20 days bollinger band to the main chart, using light blue (9999ff) as the border and
            // semi-transparent blue (c06666ff) as the fill color
            c.addBollingerBand(20, 2, 0x9999ff, unchecked((int)0xc06666ff));

            // Add a 75 pixels volume bars sub-chart to the bottom of the main chart, using green/red/grey
            // for up/down/flat days
            c.addVolBars(75, 0x99ff99, 0xff9999, 0x808080);

            mainChart.layoutAxes();

            // Set up the price volue chart, which is a chart the same size as the mainChart
            // plot area and used as its backgrouind
            PlotArea p = mainChart.getPlotArea();
            XYChart pvChart = new XYChart(p.getWidth(), p.getHeight(), Chart.Transparent);
            pvChart.setPlotArea(0, 0, pvChart.getWidth() - 1, pvChart.getHeight() - 1);
            pvChart.swapXY();  // swapXY for horizontal bar chart
            pvChart.xAxis().syncAxis(mainChart.yAxis());

            // Add price vol layers to the pyChart
            double[] volDataY = { 0, 100, 200, 300, 200, 100, 0 };
            double[] priceDataX = { 100, 110, 120, 130, 140, 150, 160 };
            // The visible candlestick number for the starting and end points of the bars
            int PVstartIndex = 0;
            int PVendIndex = 29;
            // Convert from candlestick number to pixel coordinates
            int startOffset = mainChart.getXCoor(PVstartIndex - 0.5) - p.getLeftX();
            int endOffset = mainChart.getXCoor(PVendIndex) - p.getLeftX();
            addPriceVolLayer(pvChart, startOffset, endOffset, priceDataX, volDataY, 0xffcccc);

            double[] volDataY2 = { 0, 300, 200, 300, 100, 50, 0 };
            double[] priceDataX2 = { 80, 85, 90, 95, 100, 105, 115 };
            int PVstartIndex2 = 30;
            int PVendIndex2 = 59;
            int startOffset2 = mainChart.getXCoor(PVstartIndex2 - 0.5) - p.getLeftX();
            int endOffset2 = mainChart.getXCoor(PVendIndex2) - p.getLeftX();
            addPriceVolLayer(pvChart, startOffset2, endOffset2, priceDataX2, volDataY2, 0xffcccc);

            double[] testDataY3 = { 0, 300, 200, 300, 100, 500, 0 };
            double[] testDataX3 = { 100, 110, 120, 130, 140, 150, 160 };
            addPriceVolLayer(pvChart, p.getWidth(), p.getWidth() - 100, testDataX3, testDataY3, 0xccffcc);

            // use the price volume chart as the mainChart background
            mainChart.setResource("pvChart", pvChart.makeChart());
            p.setBackground("@/pvChart", Chart.TopLeft);

            // Append a 14-days RSI indicator chart (75 pixels high) after the main chart. The main RSI line
            // is purple (800080). Set threshold region to +/- 20 (that is, RSI = 50 +/- 25). The
            // upper/lower threshold regions will be filled with red (ff0000)/blue (0000ff).
            c.addRSI(75, 14, 0x800080, 20, 0xff0000, 0x0000ff);

            // Append a 12-days momentum indicator chart (75 pixels high) using blue (0000ff) color.
            c.addMomentum(75, 12, 0x0000ff);

            // Output the chart
            viewer.Chart = c;
        }
    }
}

//==== End of Code ====
pvchart.png

  Re: Finance Chart volume profile sample request (C#)
Posted by Brian Hui on Jan-16-2024 14:56
Attachments:
Thanks a lot for the sampe, it saved me a lot of time. I tried to add the code with same sample data into the interactive finance chart. I have below questions

1. After pvChart.swapXY() and pvChart.xAxis().syncAxis(mainChart.yAxis()), I found the xAxis of the pvChart is not follow the movement of mainChart.yAxis value.

2. I used the same sample data of your example (priceDataX = { 100, 110, 120, 130, 140, 150, 160 }), it is obvious that the position of the priceDataX are not match with the values of mainchart.yAxis.

Thanks,
Brian
chart1.png

  Re: Finance Chart volume profile sample request (C#)
Posted by Peter Kwan on Jan-16-2024 19:03
Attachments:
Hi Brian,

Sorry for this problem. I forgot that the x-axis for a bar chart is "indented" by default, while the y-axis is not indented. To solve the problem, please add the following line to disable indenting the x-axis:

pvChart.xAxis().setIndent(false);

By default, the axis scale starts and ends at the axis end points. If the axis is from 0 to 100, and there is a data point at 0, the point will be plotted at an axis end point.

However, for a bar chart, if a bar is at 0, it means the "center" of the bar is at 0. So half of the bar will be outside the axis. So for a bar chart, the axis scale will default to "indented" to shift the axis scale inwards. The setIndent can be used to disable indentation.

https://www.advsofteng.com/doc/cdnet.htm#Axis.setIndent.htm

Best Regards
Peter Kwan
scrshot.png

  Re: Finance Chart volume profile sample request (C#)
Posted by Peter Kwan on Jan-16-2024 19:11
Hi Brian,

I found another cosmetic issue. The right y-axis is darker than expected. To solve the problem, in the pvChart.setPlotArea(....) line, we need to set the border to transparent:

pvChart.setPlotArea(0, 0, pvChart.getWidth() - 1, pvChart.getHeight() - 1, Chart.Transparent, -1, Chart.Transparent);

Best Regards
Peter Kwan

  Re: Finance Chart volume profile sample request (C#)
Posted by Peter Kwan on Jan-16-2024 19:17
Hi Brian,

After some thoughts, I think the best way to configure the plotarea is simply:

pvChart.setPlotArea(0, 0, pvChart.getWidth(), pvChart.getHeight());

Best Regards
Peter Kwan

  Re: Finance Chart volume profile sample request (C#)
Posted by Brian Hui on Jan-23-2024 22:51
It works. Thanks!