|
Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Takeshi on Jan-02-2021 17:02 |
|
Hi Peter,
Could I ask for your insightful opinion on how to draw a spreadsheet-like XY Chart and print it underneath finance chart, please?
The first image shows the data calculated in excel file and it can later be imported into program. I am wondering if I could insert the data of 'Percent Above 20Day MA' into cells and associate it to finance chart with color scales (min 0 & max 100, numbers are hidden), as highlighted in the second image which has been done by others. The timestamps have to be synchronized.
In addition, would it be possible to insert legends to the right of the XY Chart as shown in the second image as well?
I am using Qt C++ for your information please.
Thank you so much for your time.
Best Regards,
Takeshi
|
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Peter Kwan on Jan-09-2021 23:32 |
|
Hi Takeshi,
Sorry for the late reply.
For your case, you can add a discrete heat map in a custom indicator. The following post has some information about a discrete heat map.
https://www.chartdir.com/forum/download_thread.php?bn=chartdir_support&thread=1547024116#N1547084322
In brief, it is like:
FinanceChart *c = new FinanceChart(.....);
... set up FinanceChart as usual and add the main chart and indicators ...
//
// Below is an example to add the discrete heat map
//
// Assume you have 3 rows of cells
const char* labels[] = { "AAA", "BBB", "CCC" };
int labelCount = (int)(sizeof(labels)/sizeof(*labels));
// Generate some random data for testing. The number of cells per row should
// be equal to the number of visible timeStamps.
RanSeries r(999);
DoubleArray AAAData = r.getSeries(timeStamps.len - extraDays, -100, 100);
DoubleArray BBBData = r.getSeries(timeStamps.len - extraDays, -100, 100);
DoubleArray CCCData = r.getSeries(timeStamps.len - extraDays, -100, 100);
// Add an empty indicator chart
XYChart* t = c->addIndicator(75);
// Add the labels to the y-axis
t->yAxis()->setLinearScale(0, labelCount - 1, StringArray(labels, labelCount));
t->yAxis()->setIndent(true);
c->layout();
// We can use a hidden color axis to translate the cell values to colors
ColorAxis* cAxis = t->addContourLayer(DoubleArray(), DoubleArray(), DoubleArray())->colorAxis();
cAxis->setLinearScale(-100, 100);
int colors[] = { 0xff0000, 0xffffff, 0x00ff00 };
cAxis->setColorGradient(true, IntArray(colors, (int)(sizeof(colors)/sizeof(*colors))));
// All the cell data
DoubleArray allData[] = { AAAData, BBBData, CCCData };
// Use the DrawArea to draw the cells as rectangles
DrawArea* d = t->makeChart();
for (int i = 0; i < closeData.len - extraDays; ++i) {
for (int j = 0; j < (int)(sizeof(allData)/sizeof(*allData)); ++j) {
int color = cAxis->getColor(allData[j][i]);
d->rect(t->getXCoor(i - 0.5), t->getYCoor(j + 0.5), t->getXCoor(i + 0.5), t->getYCoor(j - 0.5), color, color);
}
}
... display chart as usual ...
Regards
Peter Kwan |
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Takeshi on Jan-31-2021 14:21 |
|
Hi Peter,
Thank you so much for the solution. It really helps a lot!
However, I am encountering a problem of synchronizing x-axis of heat map to the finance chart.
My idea is to produce a function of heat map and associate that into the FinanceChart.h.
Below is my code:
public: XYChart* addMarketBreadthHM(int height, int color_low, int color_high)
{
// Add an empty indicator chart
XYChart *c = addIndicator(height);
// Add the labels to the y-axis
int sectorno = m_marketbreadthsector.size(); // sectorno represents number of rows
c->yAxis()->setLinearScale(0, sectorno - 1, QStrVecToStringArray(m_marketbreadthsector));
c->yAxis()->setIndent(true);
// We can use a hidden color axis to translate the cell values to colors
ColorAxis* cAxis = c->addContourLayer(DoubleArray(), DoubleArray(), DoubleArray())->colorAxis();
cAxis->setLinearScale(0, 100);
int colors[] = {color_low,0xffffff,color_high};
cAxis->setColorGradient(true, IntArray(colors, (int)(sizeof(colors)/sizeof(*colors))));
// Use the DrawArea to draw the cells as rectangles
DrawArea* d = c->makeChart();
for (int i = 0; i < m_closeData.len - m_extraPoints; ++i) {
for (int j = 0; j < sectorno; ++j) {
int color = cAxis->getColor(m_marketbreadth[j][i]); // m_marketbreadth contains heat map data
d->rect(c->getXCoor(i - 0.5), c->getYCoor(j + 0.5), c->getXCoor(i + 0.5), c->getYCoor(j - 0.5), color, color);
}
}
return c;
}
Also, as shown in the attached image, the x-axis tick density of RSI and MACD are changed and different from the mainchart after adding the heat map.
Please kindly let me know if there is any problem with my code.
Thank you so much for your time.
Best Regards,
Takeshi |
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Takeshi on Jan-31-2021 14:25 |
|
The image in my preceding post was not uploaded successfully. My apologies. The image has been attached in this post.
|
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Peter Kwan on Feb-02-2021 01:41 |
|
Hi Takeshi,
Sorry for this problem. There is a bug in my original code.
I tested the code and it worked. Then I rearrange the lines to make it looks nicer, and this introduced the bug.
In my original code, there is a line:
c->layout();
This line must be there, but not in the position in the code in my last message. It should be put before addIndicator. So for your subroutine, it should be like:
public: XYChart* addMarketBreadthHM(int height, int color_low, int color_high)
{
// Must layout first
layout();
// Add an empty indicator chart
XYChart *c = addIndicator(height);
.........
}
In my previous code, we need to know the x-axis scale to correctly draw the cells. So we need to layout the chart first to determine the x-axis scale.
If we layout after addIndicator, then it will also layout the MarketBreadth chart too (as part of the FinanceChart) while it is still empty. The MarketBreadth will then be empty in the FinanceChart. That's why the layout must occur before addIndicator.
Regards
Peter Kwan |
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Takeshi on Feb-10-2021 22:48 |
|
Hi Peter,
I would like to wish you a happy, healthy Chinese New Year in advance.
Thank you so much for your help, it again works like a charm.
However I am facing another problem, I would really appreciate if you could have a look.
Please kindly refer to the attached image, currently the addzone() is above addsidevollayer(), may I know how I could bring up the sidevollayer for 1 layer so that it won't be blocked by addzone which is in green color?
My current framework is as follows:
PlotArea* p = mainchart->getPlotArea();
XYChart* pvChart = new XYChart(p->getWidth(), p->getHeight() + size().height(), Chart::Transparent);
pvChart->setPlotArea(0, 0, pvChart->getWidth() , pvChart->getHeight()- size().height());
pvChart->swapXY();
pvChart->xAxis()->syncAxis(mainchart->yAxis());
.......
addSideVolLayer(......); <===========
.......
mainchart->layoutAxes();
mainchart->setResource("pvChart", pvChart->makeChart());
p->setBackground("@/pvChart", Chart::TopLeft);
.......
addIndicator(......);
.......
mainchart->layout();
mainchart->addText(......);
.......
c->xAxis()->addZone(boxLeft, boxRight, 0xE6FFEB); <===========
.......
DrawArea *d = m->initDynamicLayer();
d->rect(......);
.......
Please let me know if you need more information about my code.
Thank you once again.
Best Regards,
Takeshi
|
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Peter Kwan on Feb-11-2021 01:46 |
|
Hi Takeshi,
I forgot how you implement addSideVolLayer. Is it drawn using the "DrawArea" object returned from BaseChart.getDrawArea?
Things drawn using the "DrawArea" from BaseChart.getDrawArea are painted on the background of the chart image. addZone always draws on the background of the plot area, which is above the chart background.
If the above is the cause of the problem, there are two methods:
(a) Use a semi-transparent color for the addZone. If both the zones and the side bars are non-transparent, then one will block the other. By using a semi-transparent color, both can be seen. For example:
c->xAxis()->addZone(boxLeft, boxRight, 0xa086FF8B)
(b) Instead of using addZone, you can use the "DrawArea" from BaseChart.getDrawArea to draw the zones too. The zones are just rectangles. You can either draws the rectangles in your addSideVolLayer, or you can create extra method addZoneLayer to draw the rectangles.
Hope this can help.
Regards
Peter Kwan |
Re: Adding spreadsheet-like XY Chart to Finance Chart |
Posted by Takeshi on Feb-17-2021 02:15 |
|
Hi Peter,
Thank you so much for the reply, both solutions work perfectly.
Regarding to the heat map, I found another problem is that I can only produce it once to the FinanceChart.
It appears empty if I add additional heat maps, but other XYchart added in between the empty heat maps is working as normal.
Please find the attached image for your kind reference.
I am trying to show the x-axis tick in front of the heat map, so I trigger the layout() after the XYChart *c = addIndicator(height), but seemingly I have done something wrong.
Below is my subroutine:
public: XYChart* addMarketBreadthHM(int height, int color_low, int color_high)
{
// Add an empty indicator chart
XYChart *c = addIndicator(height);
c->setPlotArea(c->getPlotArea()->getLeftX(),c->getPlotArea()->getTopY(),
c->getPlotArea()->getWidth(),height, Chart::Transparent,
-1,0x949494,Chart::Transparent,0xc0c0c0);
int sectorno = m_marketbreadthsector.size();
std::vector<std::string> m_marketbreadthsector_str(sectorno);
for(int i=0;i<sectorno;i++)
{
std::string strbuff = m_marketbreadthsector[i].toUtf8().constData();
m_marketbreadthsector_str[i] = strbuff.substr(0, 2);
}
// Add the labels to the y-axis
c->yAxis()->setLinearScale(0, sectorno - 1, StrVecToStringArray(m_marketbreadthsector_str));
c->yAxis()->setIndent(true);
c->yAxis()->setReverse();
c->yAxis()->setTickColor(Chart::Transparent,Chart::Transparent);
c->yAxis()->setTopMargin(0);
// We can use a hidden color axis to translate the cell values to colors
ColorAxis* cAxis = c->addContourLayer(DoubleArray(), DoubleArray(), DoubleArray())->colorAxis();
cAxis->setLinearScale(0, 100);
int colors[] = {color_low,0xffffff,color_high};
cAxis->setColorGradient(true, IntArray(colors, (int)(sizeof(colors)/sizeof(*colors))));
addLineIndicator2(c,DoubleArray(), Chart::Transparent,"");
//We need to layout the chart first to determine the x-axis scale
layout();
// Use the DrawArea to draw the cells as rectangles
DrawArea* d = c->getDrawArea();
for (int i = m_extraPoints; i < m_closeData.len; ++i) {
for (int j = 0; j < sectorno; ++j) {
int color = cAxis->getColor(m_marketbreadth[j][i]);
d->rect(c->getXCoor(i - m_extraPoints - 0.5), c->getYCoor(j + 0.5),
c->getXCoor(i - m_extraPoints + 0.5), c->getYCoor(j - 0.5), color, color);
}
}
return c;
}
Thank you so much, Peter.
Best Regards,
Takeshi
|
|