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

Message ListMessage List     Post MessagePost Message

  How to track the value of extra indicator in FinanceChart
Posted by James on Feb-07-2021 17:54
Attachments:
Hi,
    I added an indicator chart to a FinanceChart by:
    
    XYChart* c_youzi = c->addIndicator(75);  //user indicator

    and this chart works fine.


    But I can't track the value of this indicator chart.

    The tracking routine is here:

void CDongFang_Data_AnalyseView::trackFinance(MultiChart *m, int mouseX)
{

#if 1
// Clear the current dynamic layer and get the DrawArea object to draw on it.
DrawArea *d = m->initDynamicLayer();

// It is possible for a FinanceChart to be empty, so we need to check for it.
if (m->getChartCount() == 0)
return;

// Get the data x-value that is nearest to the mouse
int xValue = (int)(((XYChart *)m->getChart(0))->getNearestXValue(mouseX));

// Iterate the XY charts (main price chart and indicator charts) in the FinanceChart
XYChart *c = 0;
for (int i = 0; i < m->getChartCount(); ++i) {
c = (XYChart *)m->getChart(i);

// Variables to hold the legend entries
std::ostringstream ohlcLegend;
std::vector<std::string> legendEntries;

// Iterate through all layers to find the highest data point
for (int j = 0; j < c->getLayerCount(); ++j) {
Layer *layer = c->getLayerByZ(j);
int xIndex = layer->getXIndexOf(xValue);
int dataSetCount = layer->getDataSetCount();

// In a FinanceChart, only layers showing OHLC data can have 4 data sets
if (dataSetCount == 4) {
double highValue = layer->getDataSet(0)->getValue(xIndex);
double lowValue = layer->getDataSet(1)->getValue(xIndex);
double openValue = layer->getDataSet(2)->getValue(xIndex);
double closeValue = layer->getDataSet(3)->getValue(xIndex);

if (closeValue != Chart::NoValue) {
// Build the OHLC legend
ohlcLegend << "      <*block*>";
ohlcLegend << "Open: " << c->formatValue(openValue, "{value|P4}");
ohlcLegend << ", High: " << c->formatValue(highValue, "{value|P4}");
ohlcLegend << ", Low: " << c->formatValue(lowValue, "{value|P4}");
ohlcLegend << ", Close: " << c->formatValue(closeValue, "{value|P4}");

// We also draw an upward or downward triangle for up and down days and the %
// change
double lastCloseValue = layer->getDataSet(3)->getValue(xIndex - 1);
if (lastCloseValue != Chart::NoValue) {
double change = closeValue - lastCloseValue;
double percent = change * 100 / closeValue;
std::string symbol = (change >= 0) ?
"<*font,color=990000*><*img=@triangle,width=8,color=990000*>" :  //008800
"<*font,color=00cc00*><*img=@invertedtriangle,width=8,color=00CC00*>";  //cc0000

ohlcLegend << "  " << symbol << " " << c->formatValue(change, "{value|P4}");
ohlcLegend << " (" << c->formatValue(percent, "{value|2}") << "%)<*/font*>";
}

ohlcLegend << "<*/*>";
}
}
else {
// Iterate through all the data sets in the layer
for (int k = 0; k < layer->getDataSetCount(); ++k) {
DataSet *dataSet = layer->getDataSetByZ(k);

std::string name = dataSet->getDataName();
double value = dataSet->getValue(xIndex);
if ((0 != name.size()) && (value != Chart::NoValue)) {

// In a FinanceChart, the data set name consists of the indicator name and its
// latest value. It is like "Vol: 123M" or "RSI (14): 55.34". As we are
// generating the values dynamically, we need to extract the indictor name
// out, and also the volume unit (if any).

// The volume unit
std::string unitChar;

// The indicator name is the part of the name up to the colon character.
int delimiterPosition = (int)name.find(':');
if (name.npos != delimiterPosition) {

// The unit, if any, is the trailing non-digit character(s).
int lastDigitPos = (int)name.find_last_of("0123456789");
if ((name.npos != lastDigitPos) && (lastDigitPos + 1 < (int)name.size()) &&
(lastDigitPos > delimiterPosition))
unitChar = name.substr(lastDigitPos + 1);

name.resize(delimiterPosition);
}

// In a FinanceChart, if there are two data sets, it must be representing a
// range.
if (dataSetCount == 2) {
// We show both values in the range in a single legend entry
value = layer->getDataSet(0)->getValue(xIndex);
double value2 = layer->getDataSet(1)->getValue(xIndex);
name = name + ": " + c->formatValue(min(value, value2), "{value|P3}");
name = name + " - " + c->formatValue(max(value, value2), "{value|P3}");
}
else  {  //james mod
// In a FinanceChart, only the layer for volume bars has 3 data sets for
// up/down/flat days
if (dataSetCount == 3) {
// The actual volume is the sum of the 3 data sets.
value = layer->getDataSet(0)->getValue(xIndex) + layer->getDataSet(1
)->getValue(xIndex) + layer->getDataSet(2)->getValue(xIndex);
}

// Create the legend entry
name = name + ": " + c->formatValue(value, "{value|P3}") + unitChar;
}

// Build the legend entry, consist of a colored square box and the name (with
// the data value in it).
std::ostringstream legendEntry;
legendEntry << "<*block*><*img=@square,width=8,edgeColor=000000,color="
<< std::hex << dataSet->getDataColor() << "*> " << name << "<*/*>";
legendEntries.push_back(legendEntry.str());
}
}
}
}

// Get the plot area position relative to the entire FinanceChart
PlotArea *plotArea = c->getPlotArea();
int plotAreaLeftX = plotArea->getLeftX() + c->getAbsOffsetX();
int plotAreaTopY = plotArea->getTopY() + c->getAbsOffsetY();

// The legend begins with the date label, then the ohlcLegend (if any), and then the
// entries for the indicators.
std::ostringstream legendText;
legendText << "<*block,valign=top,maxWidth=" << (plotArea->getWidth() - 5)
<< "*><*font=arialbd.ttf*>[" << c->xAxis()->getFormattedLabel(xValue, "mmm dd, yyyy")
<< "]<*/font*>" << ohlcLegend.str();
for (int i = ((int)legendEntries.size()) - 1; i >= 0; --i) {
legendText << "      " << legendEntries[i];
}
legendText << "<*/*>";

// Draw a vertical track line at the x-position
d->vline(plotAreaTopY, plotAreaTopY + plotArea->getHeight(), c->getXCoor(xValue) +
c->getAbsOffsetX(), d->dashLineColor(0x000000, 0x0101));

// Display the legend on the top of the plot area
TTFText *t = d->text(legendText.str().c_str(), "arial.ttf", 8);
t->draw(plotAreaLeftX + 5, plotAreaTopY + 3, 0x000000, Chart::TopLeft);
t->destroy();
}

#endif
}

     Where is the entrance to get my indicator's data ?
     What's the meaning of '{value|P3}'  P2, P4...?

   Thanks

    Regards

   James
chartdirector-indicator.png

  Re: How to track the value of extra indicator in FinanceChart
Posted by James on Feb-08-2021 09:37
Attachments:
Dear All,
   I've checked the sample code, there is a judge of dataset name:

    std::string name = dataSet->getDataName();
double value = dataSet->getValue(xIndex);
if ((0 != name.size()) && (value != Chart::NoValue)) {   <---- name.size()
//---------------------------------------
       So, you should defined the dataset name at the time it is added in layer, like this:
// Add a bar chart layer using the given data
BarLayer *barYouzi =  c_youzi->addBarLayer(DoubleArray(dyouzi, duration ),0xff00ff,"YouZi",0);    //<------"Youzi" is the name of dataset

       Now the legend box displays the value of my indicator

      Regards
chartdirector-legendbox.png