JKQTPlotter trunk/v5.0.0
an extensive Qt5+Qt6 Plotter framework (including a feature-richt plotter widget, a speed-optimized, but limited variant and a LaTeX equation renderer!), written fully in C/C++ and without external dependencies
Loading...
Searching...
No Matches
Example (JKQTPlotter): Financial Chart (Candlestick/OHLC) Example

This project (see financialgraphs demonstrates the use of JKQTPFinancialGraph to visualize financial data (i.e. market price development of stocks, derivatives, ...).

The source code of the main application is (see financialgraphs.cpp.

Here is a short summary of the important parts of the code:

First we need to set up the plotter and then generate some data for our plot. Here we use a simple random walk (with normally distributed steps) to simulate the price of some virtual stock. We simulate severals steps ofer NDays days and then calculate the necessary statistics over each day (i.e. the opening and closing price, as well as the daily maximum and minimum). Alternatively you could of course also load actual stock price data and read it in youself.

// 1. setup a plotter window and get a pointer to the internal datastore (for convenience)
// 2. now we create 5 datacolumns with length Ndays entries in the datastore
// these will later hold the time-step and simulated market data of two stocks
const size_t NDays=31;
const size_t columnT=ds->addColumn("time");
const size_t columnO1=ds->addColumn("open(stock 1)");
const size_t columnC1=ds->addColumn("close(stock 1)");
const size_t columnL1=ds->addColumn("low(stock 1)");
const size_t columnH1=ds->addColumn("high(stock 1)");
const size_t columnO2=ds->addColumn("open(stock 2)");
const size_t columnC2=ds->addColumn("close(stock 2)");
const size_t columnL2=ds->addColumn("low(stock 2)");
const size_t columnH2=ds->addColumn("high(stock 2)");
const QDate t0(2024,1,8); // start date
// 3. now we simulate stock market data with a simple random walk
// with a few steps per day that are summmarized into the four
// properties Open,Close,Low,High for each day
double price1=30; // start price of stock 1
double price2=25; // start price of stock 2
const size_t stepsPerDay=20;
std::random_device rd; // random number generators:
std::mt19937 gen{rd()};
gen.seed(12352);
std::normal_distribution<double> dist1(0.001, 0.6);
std::normal_distribution<double> dist2(-0.0001, 0.4);
for (size_t t=0; t<NDays; t+=1) {// iterate over all simulated days (we don't care for weekends)
// step time from noon to noon in steps of days
const QDate d=t0.addDays(t);
ds->appendToColumn(columnT, QDateTime(d,QTime(12,0,0)).toMSecsSinceEpoch());
// the open-Value is the start-price of each day:
ds->appendToColumn(columnO1, price1);
ds->appendToColumn(columnO2, price2);
// now we iterate the market over the day
double L1=price1, L2=price2, H1=price1, H2=price2;
for (size_t i=0; i<stepsPerDay; i++) { // iterate over week days (Mon-Fri)
// prices are calculated from a sinple random walk (the while-loops ensure that we have positive prices only
double np;
while ((np=price1+dist1(gen))<=0.0); price1=np;
while ((np=price2+dist2(gen))<=0.0); price2=np;
// now we track the highest/lowest prices
L1=qMin(L1, price1);
L2=qMin(L2, price2);
H1=qMax(H1, price1);
H2=qMax(H2, price2);
}
// the close-Value is the final price of each day:
ds->appendToColumn(columnC1, price1);
ds->appendToColumn(columnC2, price2);
// finally we just have to add the highest and lowest prices of each day:
ds->appendToColumn(columnL1, L1);
ds->appendToColumn(columnL2, L2);
ds->appendToColumn(columnH1, H1);
ds->appendToColumn(columnH2, H2);
}
This class manages data columns (with entries of type double ), used by JKQTPlotter/JKQTBasePlotter t...
Definition jkqtpdatastorage.h:282
void appendToColumn(size_t column, double value)
adds a value value to the column column. This changes the column length (number of rows).
size_t addColumn(JKQTPColumn col)
add a new column to the datastore and return its ID
plotter widget for scientific plots (uses JKQTBasePlotter to do the actual drawing)
Definition jkqtplotter.h:364
JKQTPDatastore * getDatastore()
returns a pointer to the datastore used by this object
Definition jkqtplotter.h:611

Now we have all columns necessary for two JKQTPFinancialGraph graphs.The first graph will be drawn in the CandleStick style and the second in the OHLC-sytle:

// 3. create two JKQTPFinancialGraph to display the data:
JKQTPFinancialGraph* graphCandleStick=new JKQTPFinancialGraph(&plot);
graphCandleStick->setXColumn(columnT);
graphCandleStick->setOpenColumn(columnO1);
graphCandleStick->setHighColumn(columnH1);
graphCandleStick->setLowColumn(columnL1);
graphCandleStick->setCloseColumn(columnC1);
graphCandleStick->setTitle(QObject::tr("stock 1 (candlestick)"));
graphCandleStick->setCandlestickTwoColor(QColor("darkgreen"), QColor("maroon"));
graphOHLC->setXColumn(columnT);
graphOHLC->setOpenColumn(columnO2);
graphOHLC->setHighColumn(columnH2);
graphOHLC->setLowColumn(columnL2);
graphOHLC->setCloseColumn(columnC2);
graphOHLC->setTitle(QObject::tr("stock 2 (OHLC)"));
graphOHLC->setOHLCTwoColor(QColor("darkgreen"), QColor("maroon"));
// 4. add the graphs to the plot, so it is actually displayed
plot.addGraph(graphCandleStick);
plot.addGraph(graphOHLC);
This class draws an Open-High-Low-Close (OHLC) or candle-stick graph typically representing financial...
Definition jkqtpfinancial.h:92
void setGraphType(FinancialGraphType __value)
type of the financial graph (OHLC or candle-stick)
void setOpenColumn(int __value)
column for the "Open" value of the financial graph
void setOHLCTwoColor(QColor cPositive, QColor cNegative)
sets graphType = FinancialGraphType::OHLC and sets the positive and negative color (for fill and line...
void setCandlestickTwoColor(QColor cPositive, QColor cNegative)
sets graphType = FinancialGraphType::CandleStick and sets the positive and negative color (for fill a...
void setLowColumn(int __value)
column for the "Low" value of the financial graph
@ CandleStick
candlestick graphs
Definition jkqtpfinancial.h:97
@ OHLC
OHLC (Open-High-Low-Close) graphs.
Definition jkqtpfinancial.h:98
void setHighColumn(int __value)
column for the "High" value of the financial graph
void setCloseColumn(int __value)
column for the "Close" value of the financial graph
virtual void setTitle(const QString &__value)
sets the title of the plot (for display in key!).
void setXColumn(int __value)
the column that contains the x-component of the datapoints
void addGraph(JKQTPPlotElement *gr)
Definition jkqtplotter.h:784

Finally we only have to format the plot and coordinate axes slightly to produce a nicer and better readable plot:

// 5. scale the plot so the graph is contained and make x-axis a date-axis
plot.getXAxis()->setAxisLabel("time");
plot.getXAxis()->setTickLabelAngle(35); // rotate axis tick label by 35°, so they are readable
plot.getYAxis()->setAxisLabel("stock price [\\$]");
plot.zoomToFit();
void setPosition(JKQTPKeyPosition __value)
key position inside or besides the plot area, see JKQTPKeyPositions for details and examples
Definition jkqtpkey.h:260
void setTickLabelAngle(double __value)
rotation angle of tick labels [-180..180], i.e. given in degrees, default is 0 (horizontal)
void setAxisLabel(const QString &__value)
axis label of the axis
void setTickLabelType(JKQTPCALabelType __value)
indicates how to draw the labels
void zoomToFit(bool zoomX=true, bool zoomY=true, bool includeX0=false, bool includeY0=false, double scaleX=1.05, double scaleY=1.05)
this method zooms the graph so that all plotted datapoints are visible.
Definition jkqtplotter.h:1039
JKQTPVerticalAxisBase * getYAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis)
returns the y-axis objet of the plot
Definition jkqtplotter.h:713
JKQTPBaseKey * getMainKey()
retuns the main key object
Definition jkqtplotter.h:412
JKQTPHorizontalAxisBase * getXAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis)
returns the x-axis objet of the plot
Definition jkqtplotter.h:711
@ JKQTPKeyInsideTopLeft
the key is positioned inside on the top-left
Definition jkqtptools.h:583
@ JKQTPCALTdate
show numbers as dates
Definition jkqtptools.h:455

The result looks like this:

financialgraphs