mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-11-16 10:35:49 +08:00
f40bb2010d
NEW: autoscaling for barcharts works now, also when stacked and unstacked charts are combined in one plot NEW: proper styling for financial graphs in style.ini-files REWORKED: separation and gruping factor for barcharts on autoscaling doc update
338 lines
14 KiB
C++
338 lines
14 KiB
C++
/*
|
|
Copyright (c) 2008-2024 Jan W. Krieger (<jan@jkrieger.de>)
|
|
|
|
|
|
|
|
This software is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
|
the Free Software Foundation, either version 2.1 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License (LGPL) for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef jkqtpfinancial_H
|
|
#define jkqtpfinancial_H
|
|
|
|
#include <QString>
|
|
#include <QPainter>
|
|
#include <QPair>
|
|
#include "jkqtplotter/jkqtptools.h"
|
|
#include "jkqtplotter/jkqtplotter_imexport.h"
|
|
#include "jkqtplotter/jkqtpgraphsbase.h"
|
|
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
|
|
|
|
|
/** \brief This class draws an Open-High-Low-Close (OHLC) or candle-stick graph typically representing financial data
|
|
* \ingroup jkqtplotter_financialgraphs
|
|
*
|
|
* This graph draws either <b>candlstick charts</b>:
|
|
* \image html financialgraphs_basics_candlestick.png
|
|
* or <b>Open-High-Low-Close (OHLC) charts</b> (depending on what you set in setGraphType() ).
|
|
* \image html financialgraphs_basics_ohlc.png
|
|
*
|
|
* Here is an example graph showcasing both variants:
|
|
*
|
|
* \image html JKQTPFinancialGraph.png
|
|
*
|
|
* \see For details on the graph types see https://en.wikipedia.org/wiki/Candlestick_chart and https://en.wikipedia.org/wiki/Open-high-low-close_chart
|
|
* \see JKQTPXGraph
|
|
*
|
|
*
|
|
* \section JKQTPFinancialGraphStyling Styling the Financial Graphs
|
|
* You can control the type of graph and it's appearance with these functions (example images are in the documentation of the functions):
|
|
* - setGraphType()
|
|
* - setCandlestickTwoColor()
|
|
* - setCandlestickOneColor()
|
|
* - setOHLCTwoColor()
|
|
* .
|
|
*
|
|
* For fine-tuning, you can access the line- and fill-styles for positiove (close>open) and negative (close<open)
|
|
* items separately via:
|
|
* - lineStylePositive() and fillStylePositive()
|
|
* - lineStyleNegative() and fillStyleNegative()
|
|
* .
|
|
*
|
|
* Note that the width of the single elements for each x-value is automatically from the distance to the
|
|
* next neighbours. Here set parameter width (setWidth(), getWidth() ) is employed. It sets the relative
|
|
* amount of space that an element occupies in its part of the graph. Typically the default width is 0.8 (or 80%).
|
|
*
|
|
* \image html financialgraphs_width.png
|
|
*
|
|
*
|
|
* \section JKQTPFinancialGraphSideBySide Several Financial Graphs side-by-side
|
|
* In case you want to display several of these graphs in the same plot, you can make them appear side-by-side, even
|
|
* if they all cover the same x-values and would thus be draw atop each other. We apply the same principles that
|
|
* were used for barcharts in JKQTPBarGraphBase and add a shift-parameter (setShift() ) that shifts each element
|
|
* in the available space:
|
|
*
|
|
* \image html financialgraphs_shiftwidth.png
|
|
*
|
|
* For example for two financial graph elements per x-value one would set:
|
|
* \verbatim
|
|
* width=0.4
|
|
* shift=-0.5 / +0.5
|
|
* \endverbatim
|
|
*
|
|
* Two functions are provided (JKQTPFinancialGraph::autoscaleBoxWidthAndShift(), JKQTPFinancialGraph::autoscaleBoxWidthAndShiftSeparatedGroups() )
|
|
* that can be applied to any JKQTPFinancialGraph in the plot and will calculate all JKQTPFinancialGraphs' shift and width parameter
|
|
* in such a way that the graphs appear tidied up into groups by x-value. With these functions you don't have to calculate
|
|
* the shift and width values by hand! A call always only affects the JKQTPFinancialGraph in the plot with the same orientation
|
|
* (vertical or horizontal).
|
|
*
|
|
* \image html JKQTPFinancialGraphSidyBySide.png
|
|
*
|
|
*/
|
|
class JKQTPLOTTER_LIB_EXPORT JKQTPFinancialGraph: public JKQTPXGraph {
|
|
Q_OBJECT
|
|
public:
|
|
/** \brief types of financial graphs that can be drawn by this class */
|
|
enum FinancialGraphType {
|
|
CandleStick, //!< \brief candlestick graphs \image html JKQTPFinancialGraphCandleStick.png
|
|
OHLC //!< \brief OHLC (Open-High-Low-Close) graphs \image html JKQTPFinancialGraphOHLC.png
|
|
};
|
|
Q_ENUM(FinancialGraphType)
|
|
|
|
/** \brief class constructor */
|
|
JKQTPFinancialGraph(JKQTBasePlotter* parent=nullptr);
|
|
/** \brief class constructor */
|
|
JKQTPFinancialGraph(JKQTPlotter* parent);
|
|
|
|
/** \copydoc JKQTPXGraph::drawKeyMarker() */
|
|
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
|
|
/** \copydoc JKQTPXGraph::getKeyLabelColor() */
|
|
virtual QColor getKeyLabelColor() const override;
|
|
/** \copydoc JKQTPXGraph::draw() */
|
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
|
|
|
|
|
|
|
/** \copydoc shift */
|
|
double getShift() const;
|
|
/** \copydoc width */
|
|
double getWidth() const;
|
|
|
|
/** \copydoc m_fillStyleNegative */
|
|
JKQTPGraphFillStyleMixin &fillStyleNegative();
|
|
/** \copydoc m_fillStyleNegative */
|
|
const JKQTPGraphFillStyleMixin& fillStyleNegative() const;
|
|
/** \copydoc m_fillStylePositive */
|
|
JKQTPGraphFillStyleMixin &fillStylePositive();
|
|
/** \copydoc m_fillStylePositive */
|
|
const JKQTPGraphFillStyleMixin& fillStylePositive() const;
|
|
|
|
|
|
/** \copydoc m_lineStyleNegative */
|
|
JKQTPGraphLineStyleMixin &lineStyleNegative();
|
|
/** \copydoc m_lineStyleNegative */
|
|
const JKQTPGraphLineStyleMixin& lineStyleNegative() const;
|
|
/** \copydoc m_lineStylePositive */
|
|
JKQTPGraphLineStyleMixin &lineStylePositive();
|
|
/** \copydoc m_lineStylePositive */
|
|
const JKQTPGraphLineStyleMixin& lineStylePositive() const;
|
|
|
|
/** \copydoc JKQTPXGraph::getIndexRange() */
|
|
virtual bool getIndexRange(int &imin, int &imax) const override;
|
|
/** \copydoc JKQTPXGraph::getYMinMax() */
|
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
|
/** \copydoc JKQTPXGraph::usesColumn() */
|
|
virtual bool usesColumn(int column) const override;
|
|
|
|
|
|
|
|
/** \copydoc openColumn */
|
|
int getOpenColumn() const;
|
|
|
|
/** \copydoc closeColumn */
|
|
int getCloseColumn() const;
|
|
|
|
/** \copydoc highColumn */
|
|
int getHighColumn() const;
|
|
|
|
/** \copydoc lowColumn */
|
|
int getLowColumn() const;
|
|
/** \copydoc graphType */
|
|
FinancialGraphType getGraphType() const;
|
|
|
|
Q_PROPERTY(int openColumn READ getOpenColumn WRITE setOpenColumn)
|
|
Q_PROPERTY(int closeColumn READ getCloseColumn WRITE setCloseColumn)
|
|
Q_PROPERTY(int highColumn READ getHighColumn WRITE setHighColumn)
|
|
Q_PROPERTY(int lowColumn READ getLowColumn WRITE setLowColumn)
|
|
Q_PROPERTY(FinancialGraphType graphType READ getGraphType WRITE setGraphType)
|
|
|
|
static void clearColorAssignStore();
|
|
public Q_SLOTS:
|
|
|
|
/** \brief finds all financial charts of the same orientation and determines width and shift, so they stand side by side
|
|
*
|
|
* \param maxWidth the maximum (relative) width, that all boxes will span of the (doubled) inter-box distance
|
|
* \param shrinkFactor factor, by which the boxes are shrinked compared to the available space
|
|
*
|
|
* \note This function will scale ALL graphs of the parent plot, which were derived from JKQTPFinancialGraph, that match in orientation (currently all).
|
|
*/
|
|
virtual void autoscaleBoxWidthAndShift(double maxWidth=0.8, double shrinkFactor=0.8);
|
|
|
|
/** \brief equivalent to \c autoscaleBoxWidthAndShift(groupWidth,0.8);
|
|
*/
|
|
void autoscaleBoxWidthAndShiftSeparatedGroups(double groupWidth=0.65);
|
|
/** \copydoc shift */
|
|
void setShift(double __value);
|
|
/** \copydoc width */
|
|
void setWidth(double __value);
|
|
/** \copydoc graphType */
|
|
void setGraphType(FinancialGraphType __value);
|
|
|
|
/** \brief set outline and fill color at the same time, for both positive and negative boxes
|
|
*
|
|
* \param cPositive color for positive items (close>open)
|
|
* \param cNegative color for negative items (close<open)
|
|
*/
|
|
virtual void setColor(QColor cPositive, QColor cNegative);
|
|
/** \brief set outline and fill color at the same time, for both positive and negative boxes
|
|
*
|
|
* \param linePositive line-color for positive items (close>open)
|
|
* \param fillPositive fill-color for positive items (close>open)
|
|
* \param lineNegative line-color for negative items (close<open)
|
|
* \param fillNegative fill-color for negative items (close<open)
|
|
*/
|
|
virtual void setColor(QColor linePositive, QColor fillPositive, QColor lineNegative, QColor fillNegative);
|
|
/** \brief sets graphType = FinancialGraphType::CandleStick and sets the positive and negative color (for fill and line equal!)
|
|
*
|
|
* \param cPositive color for positive items (close>open)
|
|
* \param cNegative color for negative items (close<open)
|
|
*
|
|
* Here is an example output for <code>setCandlestickTwoColor(QColor("blue"), QColor("orange"))</code>:
|
|
*
|
|
* \image html JKQTPFinancialGraphSetCandlestickTwoColor.png
|
|
*/
|
|
void setCandlestickTwoColor(QColor cPositive, QColor cNegative);
|
|
/** \brief sets graphType = FinancialGraphType::CandleStick and sets the positive and negative fill color and a single line-color
|
|
*
|
|
* \param cPositive color for fill of positive items (close>open)
|
|
* \param cNegative color for fill of negative items (close<open)
|
|
*
|
|
* Here is an example output for <code>setCandlestickTwoColor(QColor("green"), QColor("red"), QColor("black"))</code>:
|
|
*
|
|
* \image html JKQTPFinancialGraphSetCandlestickTwoColor2.png
|
|
*/
|
|
void setCandlestickTwoColor(QColor cPositive, QColor cNegative, QColor lineCOlor);
|
|
/** \brief sets graphType = FinancialGraphType::CandleStick and sets one color \a cLine for positive and negative items, where positive items are unfilled and negative items are filled
|
|
*
|
|
* \param cLine line-color for all items and also fill-color for positive items (close>open), negative items are unfilled
|
|
*
|
|
* Here is an example output for <code>setCandlestickOneColor(QColor("black"))</code>:
|
|
*
|
|
* \image html JKQTPFinancialGraphSetCandlestickOneColor.png
|
|
*/
|
|
void setCandlestickOneColor(QColor cLine);
|
|
/** \brief sets graphType = FinancialGraphType::OHLC and sets the positive and negative color (for fill and line equal!)
|
|
*
|
|
* \param cPositive color for positive items (close>open)
|
|
* \param cNegative color for negative items (close<open)
|
|
*
|
|
* Here is an example output for <code>setOHLCTwoColor(QColor("darkblue"), QColor("darkorange"))</code>:
|
|
*
|
|
* \image html JKQTPFinancialGraphSetOHLCTwoColor.png
|
|
*/
|
|
void setOHLCTwoColor(QColor cPositive, QColor cNegative);
|
|
|
|
|
|
/** \copydoc openColumn */
|
|
void setOpenColumn(int __value);
|
|
/** \copydoc openColumn */
|
|
void setOpenColumn (size_t __value);
|
|
/** \copydoc closeColumn */
|
|
void setCloseColumn(int __value);
|
|
/** \copydoc closeColumn */
|
|
void setCloseColumn (size_t __value);
|
|
/** \copydoc highColumn */
|
|
void setHighColumn(int __value);
|
|
/** \copydoc highColumn */
|
|
void setHighColumn (size_t __value);
|
|
/** \copydoc lowColumn */
|
|
void setLowColumn(int __value);
|
|
/** \copydoc lowColumn */
|
|
void setLowColumn (size_t __value);
|
|
|
|
protected:
|
|
static QSet<JKQTBasePlotter*> parentsAlreadySeen;
|
|
/** \brief type of the financial graph (OHLC or candle-stick)
|
|
*
|
|
* \see setGraphType(), getGraphType(), FinancialGraphType
|
|
*/
|
|
FinancialGraphType graphType;
|
|
/** \brief column for the "Open" value of the financial graph
|
|
*
|
|
* \see setOpenColumn(), getOpenColumn()
|
|
*/
|
|
int openColumn;
|
|
/** \brief column for the "Close" value of the financial graph
|
|
*
|
|
* \see setCloseColumn(), getCloseColumn()
|
|
*/
|
|
int closeColumn;
|
|
/** \brief column for the "High" value of the financial graph
|
|
*
|
|
* \see setHighColumn(), getHighColumn()
|
|
*/
|
|
int highColumn;
|
|
/** \brief column for the "Low" value of the financial graph
|
|
*
|
|
* \see setLowColumn(), getLowColumn()
|
|
*/
|
|
int lowColumn;
|
|
|
|
/** \brief the width of the boxes, relative to the distance between the current and the next x-value
|
|
*
|
|
* See the following graphic to understand this concept (same principle as described in the JKQTPBarGraphBase documentation):
|
|
* \image html financialgraphs_shiftwidth.png
|
|
*/
|
|
double width;
|
|
/** \brief the shift of the boxes, relative to the distance between the current and the next x-value
|
|
*
|
|
* See the following graphic to understand this concept (same principle as described in the JKQTPBarGraphBase documentation):
|
|
* \image html financialgraphs_shiftwidth.png
|
|
*/
|
|
double shift;
|
|
/** \brief fill style for positive items (close>open)
|
|
*
|
|
* \see fillStylePositive()
|
|
*/
|
|
JKQTPGraphFillStyleMixin m_fillStylePositive;
|
|
/** \brief fill style for negative items (close<open)
|
|
*
|
|
* \see fillStyleNegative()
|
|
*/
|
|
JKQTPGraphFillStyleMixin m_fillStyleNegative;
|
|
/** \brief fill style for positive items (close>open)
|
|
*
|
|
* \see lineStylePositive()
|
|
*/
|
|
JKQTPGraphLineStyleMixin m_lineStylePositive;
|
|
/** \brief fill style for negative items (close<open)
|
|
*
|
|
* \see lineStyleNegative()
|
|
*/
|
|
JKQTPGraphLineStyleMixin m_lineStyleNegative;
|
|
/** \brief this function is used by autoscaleBoxWidthAndShift() to determine whether a given graph shall be taken into account when autoscaling.
|
|
* Typically this returns \c true for all JKQTPFinancialGraph-derved objects with the same orientation (horizontal or vertical, i.e. currently all) */
|
|
virtual bool considerForAutoscaling( JKQTPFinancialGraph* other) const;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // jkqtpfinancial_H
|