├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── doc
├── Makefile
├── README
├── make.bat
└── source
│ ├── conf.py
│ ├── examples.rst
│ ├── index.rst
│ ├── modules.rst
│ └── mpl_finance.rst
├── examples
├── data
│ ├── yahoofinance-AAPL-20040819-20180120.csv
│ ├── yahoofinance-GOOG-20040819-20180120.csv
│ ├── yahoofinance-INTC-19950101-20040412.csv
│ └── yahoofinance-SPY-20080101-20180101.csv
├── date_demo1.py
├── date_demo2.py
├── finance_demo.py
├── finance_work2.py
├── longshort.py
└── plot_day_summary_oclh_demo.py
├── mpl_finance.py
├── setup.py
├── tests.py
└── tox.ini
/.gitignore:
--------------------------------------------------------------------------------
1 | doc/build
2 | doc/examples
3 | _as_gen
4 | __pycache__
5 | *.pyc
6 | *.egg-info
7 | .tox/
8 | .cache/
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: xenial
2 | sudo: false
3 | language: python
4 | matrix:
5 | include:
6 | - python: 3.6
7 | - python: 3.7
8 | - python: 3.8
9 | install:
10 | - pip install tox-travis
11 | script: tox
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | License agreement for mpl-finance
2 | =================================
3 |
4 | 1. This LICENSE AGREEMENT is between the Matplotlib Development Team
5 | ("MDT"), and the Individual or Organization ("Licensee") accessing and
6 | otherwise using matplotlib software in source or binary form and its
7 | associated documentation.
8 |
9 | 2. Subject to the terms and conditions of this License Agreement, MDT
10 | hereby grants Licensee a nonexclusive, royalty-free, world-wide license
11 | to reproduce, analyze, test, perform and/or display publicly, prepare
12 | derivative works, distribute, and otherwise use matplotlib
13 | alone or in any derivative version, provided, however, that MDT's
14 | License Agreement and MDT's notice of copyright, i.e., "Copyright (c)
15 | 2012- Matplotlib Development Team; All Rights Reserved" are retained in
16 | matplotlib alone or in any derivative version prepared by
17 | Licensee.
18 |
19 | 3. In the event Licensee prepares a derivative work that is based on or
20 | incorporates matplotlib or any part thereof, and wants to
21 | make the derivative work available to others as provided herein, then
22 | Licensee hereby agrees to include in any such work a brief summary of
23 | the changes made to matplotlib .
24 |
25 | 4. MDT is making matplotlib available to Licensee on an "AS
26 | IS" basis. MDT MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
27 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, MDT MAKES NO AND
28 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
29 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB
30 | WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
31 |
32 | 5. MDT SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB
33 | FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR
34 | LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING
35 | MATPLOTLIB , OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF
36 | THE POSSIBILITY THEREOF.
37 |
38 | 6. This License Agreement will automatically terminate upon a material
39 | breach of its terms and conditions.
40 |
41 | 7. Nothing in this License Agreement shall be deemed to create any
42 | relationship of agency, partnership, or joint venture between MDT and
43 | Licensee. This License Agreement does not grant permission to use MDT
44 | trademarks or trade name in a trademark sense to endorse or promote
45 | products or services of Licensee, or any third party.
46 |
47 | 8. By copying, installing or otherwise using matplotlib ,
48 | Licensee agrees to be bound by the terms and conditions of this License
49 | Agreement.
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/matplotlib/mpl-finance)
2 |
3 | # This package is deprecated. Please go here for the new version: https://github.com/matplotlib/mplfinance
4 |
5 | ---
6 |
7 | ## To Install:
8 | ## [`pip install --upgrade mplfinance`](https://pypi.org/project/mplfinance/)
9 |
10 | ---
11 |
12 |
13 |
14 | ## Background
15 | My name is Daniel Goldfarb. In November 2019, I became the maintainer of `matplotlib/mpl-finance`, and immediately began work on a new version of the module, with an all new API. The old API is still available in the new package, and will likely remain so for several months, at least until we are confident that the new API provides all of the old API's functionality (and more). **This package is now deprecated. [Please follow the above links to the new module.](https://github.com/matplotlib/mplfinance)** (This deprecated package consisted of code extracted from the deprecated `matplotlib.finance` module along with a few examples of usage. The code was un-maintained for over three years.)
16 |
17 | ## Purpose
18 | It's good to have a single statement of purpose, to guide development. The original documention for the (now twice deprecated) `matplotlib.finance` says that it was a set of functions "*for collecting, analyzing and plotting financial data.*" --- I disagree with the "*for collecting*" part: ** `mplfinance` is part of `matplotlib`.** Therefore, I would say **the primary purpose of mplfinance is the visualization of financial data.** However, since analyzing financial data often involves visualization (for example moving averages, oscillators, bollinger bands, etc.) let's say this **also includes analyzing financial data** (at least to the extent that such analysis involves visualization). Putting this into a single statement to guide development going forward:
19 |
20 | ---
21 | **The `mplfinance` package provides utilities for the visualization, and visual analysis, of financial data**
22 |
23 | ---
24 |
25 | Let's leave the collection and acquistion of financial data to other packages. We will focus on visualization, and visual analysis, while other packages can focus on various ways of acquiring the data. That said, we can certainly provide APIs for interfacing with packages that acquire financial data, in order to more easily and directly visualize and analyze that data.
26 |
27 | **For more information, please see the following links:**
28 |
29 | - **[`pip install --upgrade mplfinance`](https://pypi.org/project/mplfinance/)**
30 | - **[The New API](https://github.com/matplotlib/mplfinance#newapi)**
31 | - **[Latest Release Info](https://github.com/matplotlib/mplfinance#release)**
32 | - **[Some Background History About This Package](https://github.com/matplotlib/mplfinance#history)**
33 | - **[Old API Availability](https://github.com/matplotlib/mplfinance#oldapi)**
34 | - **[README](https://github.com/matplotlib/mplfinance/blob/master/README.md)**
35 |
36 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
16 |
17 | .PHONY: help
18 | help:
19 | @echo "Please use \`make ' where is one of"
20 | @echo " html to make standalone HTML files"
21 | @echo " dirhtml to make HTML files named index.html in directories"
22 | @echo " singlehtml to make a single large HTML file"
23 | @echo " pickle to make pickle files"
24 | @echo " json to make JSON files"
25 | @echo " htmlhelp to make HTML files and a HTML help project"
26 | @echo " qthelp to make HTML files and a qthelp project"
27 | @echo " applehelp to make an Apple Help Book"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " epub3 to make an epub3"
31 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
32 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
33 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
34 | @echo " text to make text files"
35 | @echo " man to make manual pages"
36 | @echo " texinfo to make Texinfo files"
37 | @echo " info to make Texinfo files and run them through makeinfo"
38 | @echo " gettext to make PO message catalogs"
39 | @echo " changes to make an overview of all changed/added/deprecated items"
40 | @echo " xml to make Docutils-native XML files"
41 | @echo " pseudoxml to make pseudoxml-XML files for display purposes"
42 | @echo " linkcheck to check all external links for integrity"
43 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
44 | @echo " coverage to run coverage check of the documentation (if enabled)"
45 | @echo " dummy to check syntax errors of document sources"
46 |
47 | .PHONY: clean
48 | clean:
49 | rm -rf $(BUILDDIR)/*
50 |
51 | .PHONY: html
52 | html:
53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54 | @echo
55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56 |
57 | .PHONY: dirhtml
58 | dirhtml:
59 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
60 | @echo
61 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
62 |
63 | .PHONY: singlehtml
64 | singlehtml:
65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
66 | @echo
67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
68 |
69 | .PHONY: pickle
70 | pickle:
71 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
72 | @echo
73 | @echo "Build finished; now you can process the pickle files."
74 |
75 | .PHONY: json
76 | json:
77 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
78 | @echo
79 | @echo "Build finished; now you can process the JSON files."
80 |
81 | .PHONY: htmlhelp
82 | htmlhelp:
83 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
84 | @echo
85 | @echo "Build finished; now you can run HTML Help Workshop with the" \
86 | ".hhp project file in $(BUILDDIR)/htmlhelp."
87 |
88 | .PHONY: qthelp
89 | qthelp:
90 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
91 | @echo
92 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
93 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
94 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mpl_finance.qhcp"
95 | @echo "To view the help file:"
96 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mpl_finance.qhc"
97 |
98 | .PHONY: applehelp
99 | applehelp:
100 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
101 | @echo
102 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
103 | @echo "N.B. You won't be able to view it unless you put it in" \
104 | "~/Library/Documentation/Help or install it in your application" \
105 | "bundle."
106 |
107 | .PHONY: devhelp
108 | devhelp:
109 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
110 | @echo
111 | @echo "Build finished."
112 | @echo "To view the help file:"
113 | @echo "# mkdir -p $$HOME/.local/share/devhelp/mpl_finance"
114 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mpl_finance"
115 | @echo "# devhelp"
116 |
117 | .PHONY: epub
118 | epub:
119 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
120 | @echo
121 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
122 |
123 | .PHONY: epub3
124 | epub3:
125 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
126 | @echo
127 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
128 |
129 | .PHONY: latex
130 | latex:
131 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
132 | @echo
133 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
134 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
135 | "(use \`make latexpdf' here to do that automatically)."
136 |
137 | .PHONY: latexpdf
138 | latexpdf:
139 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
140 | @echo "Running LaTeX files through pdflatex..."
141 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
142 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
143 |
144 | .PHONY: latexpdfja
145 | latexpdfja:
146 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
147 | @echo "Running LaTeX files through platex and dvipdfmx..."
148 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
149 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
150 |
151 | .PHONY: text
152 | text:
153 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
154 | @echo
155 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
156 |
157 | .PHONY: man
158 | man:
159 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
160 | @echo
161 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
162 |
163 | .PHONY: texinfo
164 | texinfo:
165 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
166 | @echo
167 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
168 | @echo "Run \`make' in that directory to run these through makeinfo" \
169 | "(use \`make info' here to do that automatically)."
170 |
171 | .PHONY: info
172 | info:
173 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
174 | @echo "Running Texinfo files through makeinfo..."
175 | make -C $(BUILDDIR)/texinfo info
176 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
177 |
178 | .PHONY: gettext
179 | gettext:
180 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
181 | @echo
182 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
183 |
184 | .PHONY: changes
185 | changes:
186 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
187 | @echo
188 | @echo "The overview file is in $(BUILDDIR)/changes."
189 |
190 | .PHONY: linkcheck
191 | linkcheck:
192 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
193 | @echo
194 | @echo "Link check complete; look for any errors in the above output " \
195 | "or in $(BUILDDIR)/linkcheck/output.txt."
196 |
197 | .PHONY: doctest
198 | doctest:
199 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
200 | @echo "Testing of doctests in the sources finished, look at the " \
201 | "results in $(BUILDDIR)/doctest/output.txt."
202 |
203 | .PHONY: coverage
204 | coverage:
205 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
206 | @echo "Testing of coverage in the sources finished, look at the " \
207 | "results in $(BUILDDIR)/coverage/python.txt."
208 |
209 | .PHONY: xml
210 | xml:
211 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
212 | @echo
213 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
214 |
215 | .PHONY: pseudoxml
216 | pseudoxml:
217 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
218 | @echo
219 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
220 |
221 | .PHONY: dummy
222 | dummy:
223 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
224 | @echo
225 | @echo "Build finished. Dummy builder generates no files."
226 |
--------------------------------------------------------------------------------
/doc/README:
--------------------------------------------------------------------------------
1 | The module documentation is generated with Sphinx.
2 |
3 | Run "make html" to generate HTML. Then view build/index.html.
4 |
5 |
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Command file for Sphinx documentation
4 |
5 | if "%SPHINXBUILD%" == "" (
6 | set SPHINXBUILD=sphinx-build
7 | )
8 | set BUILDDIR=build
9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
10 | set I18NSPHINXOPTS=%SPHINXOPTS% source
11 | if NOT "%PAPER%" == "" (
12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14 | )
15 |
16 | if "%1" == "" goto help
17 |
18 | if "%1" == "help" (
19 | :help
20 | echo.Please use `make ^` where ^ is one of
21 | echo. html to make standalone HTML files
22 | echo. dirhtml to make HTML files named index.html in directories
23 | echo. singlehtml to make a single large HTML file
24 | echo. pickle to make pickle files
25 | echo. json to make JSON files
26 | echo. htmlhelp to make HTML files and a HTML help project
27 | echo. qthelp to make HTML files and a qthelp project
28 | echo. devhelp to make HTML files and a Devhelp project
29 | echo. epub to make an epub
30 | echo. epub3 to make an epub3
31 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
32 | echo. text to make text files
33 | echo. man to make manual pages
34 | echo. texinfo to make Texinfo files
35 | echo. gettext to make PO message catalogs
36 | echo. changes to make an overview over all changed/added/deprecated items
37 | echo. xml to make Docutils-native XML files
38 | echo. pseudoxml to make pseudoxml-XML files for display purposes
39 | echo. linkcheck to check all external links for integrity
40 | echo. doctest to run all doctests embedded in the documentation if enabled
41 | echo. coverage to run coverage check of the documentation if enabled
42 | echo. dummy to check syntax errors of document sources
43 | goto end
44 | )
45 |
46 | if "%1" == "clean" (
47 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
48 | del /q /s %BUILDDIR%\*
49 | goto end
50 | )
51 |
52 |
53 | REM Check if sphinx-build is available and fallback to Python version if any
54 | %SPHINXBUILD% 1>NUL 2>NUL
55 | if errorlevel 9009 goto sphinx_python
56 | goto sphinx_ok
57 |
58 | :sphinx_python
59 |
60 | set SPHINXBUILD=python -m sphinx.__init__
61 | %SPHINXBUILD% 2> nul
62 | if errorlevel 9009 (
63 | echo.
64 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
65 | echo.installed, then set the SPHINXBUILD environment variable to point
66 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
67 | echo.may add the Sphinx directory to PATH.
68 | echo.
69 | echo.If you don't have Sphinx installed, grab it from
70 | echo.http://sphinx-doc.org/
71 | exit /b 1
72 | )
73 |
74 | :sphinx_ok
75 |
76 |
77 | if "%1" == "html" (
78 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
79 | if errorlevel 1 exit /b 1
80 | echo.
81 | echo.Build finished. The HTML pages are in %BUILDDIR%/html.
82 | goto end
83 | )
84 |
85 | if "%1" == "dirhtml" (
86 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
87 | if errorlevel 1 exit /b 1
88 | echo.
89 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
90 | goto end
91 | )
92 |
93 | if "%1" == "singlehtml" (
94 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
95 | if errorlevel 1 exit /b 1
96 | echo.
97 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
98 | goto end
99 | )
100 |
101 | if "%1" == "pickle" (
102 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
103 | if errorlevel 1 exit /b 1
104 | echo.
105 | echo.Build finished; now you can process the pickle files.
106 | goto end
107 | )
108 |
109 | if "%1" == "json" (
110 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
111 | if errorlevel 1 exit /b 1
112 | echo.
113 | echo.Build finished; now you can process the JSON files.
114 | goto end
115 | )
116 |
117 | if "%1" == "htmlhelp" (
118 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
119 | if errorlevel 1 exit /b 1
120 | echo.
121 | echo.Build finished; now you can run HTML Help Workshop with the ^
122 | .hhp project file in %BUILDDIR%/htmlhelp.
123 | goto end
124 | )
125 |
126 | if "%1" == "qthelp" (
127 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
128 | if errorlevel 1 exit /b 1
129 | echo.
130 | echo.Build finished; now you can run "qcollectiongenerator" with the ^
131 | .qhcp project file in %BUILDDIR%/qthelp, like this:
132 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\mpl_finance.qhcp
133 | echo.To view the help file:
134 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\mpl_finance.ghc
135 | goto end
136 | )
137 |
138 | if "%1" == "devhelp" (
139 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
140 | if errorlevel 1 exit /b 1
141 | echo.
142 | echo.Build finished.
143 | goto end
144 | )
145 |
146 | if "%1" == "epub" (
147 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
148 | if errorlevel 1 exit /b 1
149 | echo.
150 | echo.Build finished. The epub file is in %BUILDDIR%/epub.
151 | goto end
152 | )
153 |
154 | if "%1" == "epub3" (
155 | %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
156 | if errorlevel 1 exit /b 1
157 | echo.
158 | echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
159 | goto end
160 | )
161 |
162 | if "%1" == "latex" (
163 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
164 | if errorlevel 1 exit /b 1
165 | echo.
166 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
167 | goto end
168 | )
169 |
170 | if "%1" == "latexpdf" (
171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
172 | cd %BUILDDIR%/latex
173 | make all-pdf
174 | cd %~dp0
175 | echo.
176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex.
177 | goto end
178 | )
179 |
180 | if "%1" == "latexpdfja" (
181 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
182 | cd %BUILDDIR%/latex
183 | make all-pdf-ja
184 | cd %~dp0
185 | echo.
186 | echo.Build finished; the PDF files are in %BUILDDIR%/latex.
187 | goto end
188 | )
189 |
190 | if "%1" == "text" (
191 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
192 | if errorlevel 1 exit /b 1
193 | echo.
194 | echo.Build finished. The text files are in %BUILDDIR%/text.
195 | goto end
196 | )
197 |
198 | if "%1" == "man" (
199 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
200 | if errorlevel 1 exit /b 1
201 | echo.
202 | echo.Build finished. The manual pages are in %BUILDDIR%/man.
203 | goto end
204 | )
205 |
206 | if "%1" == "texinfo" (
207 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
208 | if errorlevel 1 exit /b 1
209 | echo.
210 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
211 | goto end
212 | )
213 |
214 | if "%1" == "gettext" (
215 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
216 | if errorlevel 1 exit /b 1
217 | echo.
218 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
219 | goto end
220 | )
221 |
222 | if "%1" == "changes" (
223 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
224 | if errorlevel 1 exit /b 1
225 | echo.
226 | echo.The overview file is in %BUILDDIR%/changes.
227 | goto end
228 | )
229 |
230 | if "%1" == "linkcheck" (
231 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
232 | if errorlevel 1 exit /b 1
233 | echo.
234 | echo.Link check complete; look for any errors in the above output ^
235 | or in %BUILDDIR%/linkcheck/output.txt.
236 | goto end
237 | )
238 |
239 | if "%1" == "doctest" (
240 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
241 | if errorlevel 1 exit /b 1
242 | echo.
243 | echo.Testing of doctests in the sources finished, look at the ^
244 | results in %BUILDDIR%/doctest/output.txt.
245 | goto end
246 | )
247 |
248 | if "%1" == "coverage" (
249 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
250 | if errorlevel 1 exit /b 1
251 | echo.
252 | echo.Testing of coverage in the sources finished, look at the ^
253 | results in %BUILDDIR%/coverage/python.txt.
254 | goto end
255 | )
256 |
257 | if "%1" == "xml" (
258 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
259 | if errorlevel 1 exit /b 1
260 | echo.
261 | echo.Build finished. The XML files are in %BUILDDIR%/xml.
262 | goto end
263 | )
264 |
265 | if "%1" == "pseudoxml" (
266 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
267 | if errorlevel 1 exit /b 1
268 | echo.
269 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
270 | goto end
271 | )
272 |
273 | if "%1" == "dummy" (
274 | %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
275 | if errorlevel 1 exit /b 1
276 | echo.
277 | echo.Build finished. Dummy builder generates no files.
278 | goto end
279 | )
280 |
281 | :end
282 |
--------------------------------------------------------------------------------
/doc/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # mpl_finance documentation build configuration file, created by
4 | # sphinx-quickstart on Sat Jan 7 14:48:13 2017.
5 | #
6 | # This file is execfile()d with the current directory set to its
7 | # containing dir.
8 | #
9 | # Note that not all possible configuration values are present in this
10 | # autogenerated file.
11 | #
12 | # All configuration values have a default; values that are commented out
13 | # serve to show the default.
14 |
15 | # If extensions (or modules to document with autodoc) are in another directory,
16 | # add these directories to sys.path here. If the directory is relative to the
17 | # documentation root, use os.path.abspath to make it absolute, like shown here.
18 | #
19 | # import os
20 | # import sys
21 | # sys.path.insert(0, os.path.abspath('.'))
22 |
23 | # -- General configuration ------------------------------------------------
24 |
25 | # If your documentation needs a minimal Sphinx version, state it here.
26 | #
27 | # needs_sphinx = '1.0'
28 |
29 | # Add any Sphinx extension module names here, as strings. They can be
30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
31 | # ones.
32 | extensions = [
33 | 'sphinx.ext.autodoc', 'numpydoc', 'sphinx.ext.intersphinx',
34 | 'sphinx.ext.autosummary', 'matplotlib.sphinxext.plot_directive',
35 | ]
36 |
37 | autosummary_generate = True
38 |
39 | # Add any paths that contain templates here, relative to this directory.
40 | templates_path = ['_templates']
41 |
42 | # The suffix(es) of source filenames.
43 | # You can specify multiple suffix as a list of string:
44 | #
45 | # source_suffix = ['.rst', '.md']
46 | source_suffix = '.rst'
47 |
48 | # The encoding of source files.
49 | #
50 | # source_encoding = 'utf-8-sig'
51 |
52 | # The master toctree document.
53 | master_doc = 'index'
54 |
55 | # General information about the project.
56 | project = u'mpl_finance'
57 | copyright = u'2018, Matplotlib Developers'
58 | author = u'Matplotlib Developers'
59 |
60 | # The version info for the project you're documenting, acts as replacement for
61 | # |version| and |release|, also used in various other places throughout the
62 | # built documents.
63 | #
64 | # The short X.Y version.
65 | version = u'0.10.0'
66 | # The full version, including alpha/beta/rc tags.
67 | release = u'0.10.0'
68 |
69 | # The language for content autogenerated by Sphinx. Refer to documentation
70 | # for a list of supported languages.
71 | #
72 | # This is also used if you do content translation via gettext catalogs.
73 | # Usually you set "language" from the command line for these cases.
74 | language = None
75 |
76 | # There are two options for replacing |today|: either, you set today to some
77 | # non-false value, then it is used:
78 | #
79 | # today = ''
80 | #
81 | # Else, today_fmt is used as the format for a strftime call.
82 | #
83 | # today_fmt = '%B %d, %Y'
84 |
85 | # List of patterns, relative to source directory, that match files and
86 | # directories to ignore when looking for source files.
87 | # This patterns also effect to html_static_path and html_extra_path
88 | exclude_patterns = []
89 |
90 | # The reST default role (used for this markup: `text`) to use for all
91 | # documents.
92 | #
93 | # default_role = None
94 |
95 | # If true, '()' will be appended to :func: etc. cross-reference text.
96 | #
97 | # add_function_parentheses = True
98 |
99 | # If true, the current module name will be prepended to all description
100 | # unit titles (such as .. function::).
101 | #
102 | # add_module_names = True
103 |
104 | # If true, sectionauthor and moduleauthor directives will be shown in the
105 | # output. They are ignored by default.
106 | #
107 | # show_authors = False
108 |
109 | # The name of the Pygments (syntax highlighting) style to use.
110 | pygments_style = 'sphinx'
111 |
112 | # A list of ignored prefixes for module index sorting.
113 | # modindex_common_prefix = []
114 |
115 | # If true, keep warnings as "system message" paragraphs in the built documents.
116 | # keep_warnings = False
117 |
118 | # If true, `todo` and `todoList` produce output, else they produce nothing.
119 | todo_include_todos = False
120 |
121 |
122 | # -- Options for HTML output ----------------------------------------------
123 |
124 | # The theme to use for HTML and HTML Help pages. See the documentation for
125 | # a list of builtin themes.
126 | #
127 | # html_theme = 'alabaster'
128 |
129 | # Theme options are theme-specific and customize the look and feel of a theme
130 | # further. For a list of options available for each theme, see the
131 | # documentation.
132 | #
133 | # html_theme_options = {}
134 |
135 | # Add any paths that contain custom themes here, relative to this directory.
136 | # html_theme_path = []
137 |
138 | # The name for this set of Sphinx documents.
139 | # " v documentation" by default.
140 | #
141 | # html_title = u'mpl_finance v0.10.0'
142 |
143 | # A shorter title for the navigation bar. Default is the same as html_title.
144 | #
145 | # html_short_title = None
146 |
147 | # The name of an image file (relative to this directory) to place at the top
148 | # of the sidebar.
149 | #
150 | # html_logo = None
151 |
152 | # The name of an image file (relative to this directory) to use as a favicon of
153 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
154 | # pixels large.
155 | #
156 | # html_favicon = None
157 |
158 | # Add any paths that contain custom static files (such as style sheets) here,
159 | # relative to this directory. They are copied after the builtin static files,
160 | # so a file named "default.css" will overwrite the builtin "default.css".
161 | html_static_path = []
162 |
163 | # Add any extra paths that contain custom files (such as robots.txt or
164 | # .htaccess) here, relative to this directory. These files are copied
165 | # directly to the root of the documentation.
166 | #
167 | # html_extra_path = []
168 |
169 | # If not None, a 'Last updated on:' timestamp is inserted at every page
170 | # bottom, using the given strftime format.
171 | # The empty string is equivalent to '%b %d, %Y'.
172 | #
173 | # html_last_updated_fmt = None
174 |
175 | # If true, SmartyPants will be used to convert quotes and dashes to
176 | # typographically correct entities.
177 | #
178 | # html_use_smartypants = True
179 |
180 | # Custom sidebar templates, maps document names to template names.
181 | #
182 | # html_sidebars = {}
183 |
184 | # Additional templates that should be rendered to pages, maps page names to
185 | # template names.
186 | #
187 | # html_additional_pages = {}
188 |
189 | # If false, no module index is generated.
190 | #
191 | # html_domain_indices = True
192 |
193 | # If false, no index is generated.
194 | #
195 | # html_use_index = True
196 |
197 | # If true, the index is split into individual pages for each letter.
198 | #
199 | # html_split_index = False
200 |
201 | # If true, links to the reST sources are added to the pages.
202 | #
203 | # html_show_sourcelink = True
204 |
205 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
206 | #
207 | # html_show_sphinx = True
208 |
209 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
210 | #
211 | # html_show_copyright = True
212 |
213 | # If true, an OpenSearch description file will be output, and all pages will
214 | # contain a tag referring to it. The value of this option must be the
215 | # base URL from which the finished HTML is served.
216 | #
217 | # html_use_opensearch = ''
218 |
219 | # This is the file name suffix for HTML files (e.g. ".xhtml").
220 | # html_file_suffix = None
221 |
222 | # Language to be used for generating the HTML full-text search index.
223 | # Sphinx supports the following languages:
224 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
225 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
226 | #
227 | # html_search_language = 'en'
228 |
229 | # A dictionary with options for the search language support, empty by default.
230 | # 'ja' uses this config value.
231 | # 'zh' user can custom change `jieba` dictionary path.
232 | #
233 | # html_search_options = {'type': 'default'}
234 |
235 | # The name of a javascript file (relative to the configuration directory) that
236 | # implements a search results scorer. If empty, the default will be used.
237 | #
238 | # html_search_scorer = 'scorer.js'
239 |
240 | # Output file base name for HTML help builder.
241 | htmlhelp_basename = 'mpl_financedoc'
242 |
243 | # -- Options for LaTeX output ---------------------------------------------
244 |
245 | latex_elements = {
246 | # The paper size ('letterpaper' or 'a4paper').
247 | #
248 | # 'papersize': 'letterpaper',
249 |
250 | # The font size ('10pt', '11pt' or '12pt').
251 | #
252 | # 'pointsize': '10pt',
253 |
254 | # Additional stuff for the LaTeX preamble.
255 | #
256 | # 'preamble': '',
257 |
258 | # Latex figure (float) alignment
259 | #
260 | # 'figure_align': 'htbp',
261 | }
262 |
263 | # Grouping the document tree into LaTeX files. List of tuples
264 | # (source start file, target name, title,
265 | # author, documentclass [howto, manual, or own class]).
266 | latex_documents = [
267 | (master_doc, 'mpl_finance.tex', u'mpl\\_finance Documentation',
268 | u'Matplotlib Developers', 'manual'),
269 | ]
270 |
271 | # The name of an image file (relative to this directory) to place at the top of
272 | # the title page.
273 | #
274 | # latex_logo = None
275 |
276 | # For "manual" documents, if this is true, then toplevel headings are parts,
277 | # not chapters.
278 | #
279 | # latex_use_parts = False
280 |
281 | # If true, show page references after internal links.
282 | #
283 | # latex_show_pagerefs = False
284 |
285 | # If true, show URL addresses after external links.
286 | #
287 | # latex_show_urls = False
288 |
289 | # Documents to append as an appendix to all manuals.
290 | #
291 | # latex_appendices = []
292 |
293 | # It false, will not define \strong, \code, itleref, \crossref ... but only
294 | # \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
295 | # packages.
296 | #
297 | # latex_keep_old_macro_names = True
298 |
299 | # If false, no module index is generated.
300 | #
301 | # latex_domain_indices = True
302 |
303 |
304 | # -- Options for manual page output ---------------------------------------
305 |
306 | # One entry per manual page. List of tuples
307 | # (source start file, name, description, authors, manual section).
308 | man_pages = [
309 | (master_doc, 'mpl_finance', u'mpl_finance Documentation',
310 | [author], 1)
311 | ]
312 |
313 | # If true, show URL addresses after external links.
314 | #
315 | # man_show_urls = False
316 |
317 |
318 | # -- Options for Texinfo output -------------------------------------------
319 |
320 | # Grouping the document tree into Texinfo files. List of tuples
321 | # (source start file, target name, title, author,
322 | # dir menu entry, description, category)
323 | texinfo_documents = [
324 | (master_doc, 'mpl_finance', u'mpl_finance Documentation',
325 | author, 'mpl_finance', 'One line description of project.',
326 | 'Miscellaneous'),
327 | ]
328 |
329 | # Documents to append as an appendix to all manuals.
330 | #
331 | # texinfo_appendices = []
332 |
333 | # If false, no module index is generated.
334 | #
335 | # texinfo_domain_indices = True
336 |
337 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
338 | #
339 | # texinfo_show_urls = 'footnote'
340 |
341 | # If true, do not generate a @detailmenu in the "Top" node's menu.
342 | #
343 | # texinfo_no_detailmenu = False
344 | intersphinx_mapping = {
345 | 'python': ('https://docs.python.org/3/', None),
346 | 'numpy': ('https://docs.scipy.org/doc/numpy/', None),
347 | 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None),
348 | 'pandas': ('http://pandas.pydata.org/pandas-docs/stable', None)
349 | }
350 |
--------------------------------------------------------------------------------
/doc/source/examples.rst:
--------------------------------------------------------------------------------
1 | Examples
2 | ========
3 |
4 | .. plot:: ../../examples/date_demo1.py
5 | :include-source:
6 |
7 | .. plot:: ../../examples/date_demo2.py
8 | :include-source:
9 |
10 | .. plot:: ../../examples/finance_demo.py
11 | :include-source:
12 |
13 | .. plot:: ../../examples/finance_work2.py
14 | :include-source:
15 |
16 | .. plot:: ../../examples/longshort.py
17 | :include-source:
18 |
19 | .. plot:: ../../examples/plot_day_summary_oclh_demo.py
20 | :include-source:
21 |
--------------------------------------------------------------------------------
/doc/source/index.rst:
--------------------------------------------------------------------------------
1 | .. mpl_finance documentation master file, created by
2 | sphinx-quickstart on Sat Jan 7 14:48:13 2017.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | mpl_finance: financial helpers for matplotlib
7 | =============================================
8 |
9 | A collection of functions for analyzing and plotting financial data
10 | in combination with matplotlib.
11 |
12 | .. toctree::
13 | :maxdepth: 2
14 |
15 | examples
16 | modules
17 |
18 |
19 | This module has been extracted from the core Matplotlib code base
20 | unchanged. Now that this code is separate from the core it can pick
21 | up dependencies, like :mod:`pandas` or :mod:`scipy` and expose a more
22 | powerful API to the user.
23 |
24 | We are looking for a finance domain-expert to lead this effort!
25 |
26 |
27 | * :ref:`genindex`
28 | * :ref:`search`
29 |
--------------------------------------------------------------------------------
/doc/source/modules.rst:
--------------------------------------------------------------------------------
1 | mpl_finance
2 | ===========
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | mpl_finance
8 |
--------------------------------------------------------------------------------
/doc/source/mpl_finance.rst:
--------------------------------------------------------------------------------
1 | mpl_finance module
2 | ==================
3 |
4 | .. automodule:: mpl_finance
5 | :no-members:
6 |
7 |
8 | Daily Summary
9 | -------------
10 |
11 | .. autosummary::
12 | :toctree: _as_gen
13 | :nosignatures:
14 |
15 |
16 | plot_day_summary_oclh
17 | plot_day_summary_ohlc
18 | plot_day_summary2_ochl
19 | plot_day_summary2_ohlc
20 |
21 | Candlesticks
22 | ------------
23 |
24 |
25 | .. autosummary::
26 | :toctree: _as_gen
27 | :nosignatures:
28 |
29 | candlestick_ochl
30 | candlestick_ohlc
31 |
32 |
33 | candlestick2_ochl
34 | candlestick2_ohlc
35 |
36 | Volume Overlay
37 | --------------
38 |
39 |
40 | .. autosummary::
41 | :toctree: _as_gen
42 | :nosignatures:
43 |
44 | volume_overlay
45 | volume_overlay2
46 | volume_overlay3
47 |
48 | Other
49 | -----
50 |
51 | .. autosummary::
52 | :toctree: _as_gen
53 | :nosignatures:
54 |
55 | index_bar
56 |
--------------------------------------------------------------------------------
/examples/date_demo1.py:
--------------------------------------------------------------------------------
1 | """
2 | Show how to make date plots in matplotlib using date tick locators and
3 | formatters. See major_minor_demo1.py for more information on
4 | controlling major and minor ticks
5 |
6 | All matplotlib date plotting is done by converting date instances into
7 | days since the 0001-01-01 UTC. The conversion, tick locating and
8 | formatting is done behind the scenes so this is most transparent to
9 | you. The dates module provides several converter functions date2num
10 | and num2date
11 |
12 | This example requires an active internet connection since it uses
13 | yahoo finance to get the data for plotting
14 | """
15 |
16 | import matplotlib.pyplot as plt
17 | import pandas as pd
18 | from matplotlib.dates import DateFormatter, MonthLocator, YearLocator
19 |
20 | years = YearLocator() # every year
21 | months = MonthLocator() # every month
22 | yearsFmt = DateFormatter('%Y')
23 |
24 | quotes = pd.read_csv('data/yahoofinance-INTC-19950101-20040412.csv',
25 | index_col=0,
26 | parse_dates=True,
27 | infer_datetime_format=True)
28 |
29 | dates = quotes.index
30 | opens = quotes['Open']
31 |
32 | fig, ax = plt.subplots()
33 | ax.plot_date(dates, opens, '-')
34 |
35 | # format the ticks
36 | ax.xaxis.set_major_locator(years)
37 | ax.xaxis.set_major_formatter(yearsFmt)
38 | ax.xaxis.set_minor_locator(months)
39 | ax.autoscale_view()
40 |
41 |
42 | # format the coords message box
43 | def price(x):
44 | return '$%1.2f' % x
45 |
46 |
47 | ax.fmt_xdata = DateFormatter('%Y-%m-%d')
48 | ax.fmt_ydata = price
49 | ax.grid(True)
50 |
51 | fig.autofmt_xdate()
52 | plt.show()
53 |
--------------------------------------------------------------------------------
/examples/date_demo2.py:
--------------------------------------------------------------------------------
1 | """
2 | Show how to make date plots in matplotlib using date tick locators and
3 | formatters. See major_minor_demo1.py for more information on
4 | controlling major and minor ticks
5 | """
6 |
7 | import matplotlib.pyplot as plt
8 | import pandas as pd
9 | from matplotlib.dates import (MONDAY, DateFormatter, MonthLocator,
10 | WeekdayLocator)
11 |
12 | date1 = "2002-1-5"
13 | date2 = "2003-12-1"
14 |
15 | # every monday
16 | mondays = WeekdayLocator(MONDAY)
17 |
18 | # every 3rd month
19 | months = MonthLocator(range(1, 13), bymonthday=1, interval=3)
20 | monthsFmt = DateFormatter("%b '%y")
21 |
22 |
23 | quotes = pd.read_csv('data/yahoofinance-INTC-19950101-20040412.csv',
24 | index_col=0,
25 | parse_dates=True,
26 | infer_datetime_format=True)
27 |
28 | # select desired range of dates
29 | quotes = quotes[(quotes.index >= date1) & (quotes.index <= date2)]
30 |
31 | dates = quotes.index
32 | opens = quotes['Open']
33 |
34 |
35 | fig, ax = plt.subplots()
36 | ax.plot_date(dates, opens, '-')
37 | ax.xaxis.set_major_locator(months)
38 | ax.xaxis.set_major_formatter(monthsFmt)
39 | ax.xaxis.set_minor_locator(mondays)
40 | ax.autoscale_view()
41 | # ax.xaxis.grid(False, 'major')
42 | # ax.xaxis.grid(True, 'minor')
43 | ax.grid(True)
44 |
45 | fig.autofmt_xdate()
46 |
47 | plt.show()
48 |
--------------------------------------------------------------------------------
/examples/finance_demo.py:
--------------------------------------------------------------------------------
1 | import datetime
2 |
3 | import matplotlib.dates as mdates
4 | import matplotlib.pyplot as plt
5 | import pandas as pd
6 | from matplotlib.dates import MONDAY, DateFormatter, DayLocator, WeekdayLocator
7 |
8 | from mpl_finance import candlestick_ohlc
9 |
10 | date1 = "2004-2-1"
11 | date2 = "2004-4-12"
12 |
13 |
14 | mondays = WeekdayLocator(MONDAY) # major ticks on the mondays
15 | alldays = DayLocator() # minor ticks on the days
16 | weekFormatter = DateFormatter('%b %d') # e.g., Jan 12
17 | dayFormatter = DateFormatter('%d') # e.g., 12
18 |
19 | quotes = pd.read_csv('data/yahoofinance-INTC-19950101-20040412.csv',
20 | index_col=0,
21 | parse_dates=True,
22 | infer_datetime_format=True)
23 |
24 | # select desired range of dates
25 | quotes = quotes[(quotes.index >= date1) & (quotes.index <= date2)]
26 |
27 | fig, ax = plt.subplots()
28 | fig.subplots_adjust(bottom=0.2)
29 | ax.xaxis.set_major_locator(mondays)
30 | ax.xaxis.set_minor_locator(alldays)
31 | ax.xaxis.set_major_formatter(weekFormatter)
32 | # ax.xaxis.set_minor_formatter(dayFormatter)
33 |
34 | # plot_day_summary(ax, quotes, ticksize=3)
35 | candlestick_ohlc(ax, zip(mdates.date2num(quotes.index.to_pydatetime()),
36 | quotes['Open'], quotes['High'],
37 | quotes['Low'], quotes['Close']),
38 | width=0.6)
39 |
40 | ax.xaxis_date()
41 | ax.autoscale_view()
42 | plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
43 |
44 | plt.show()
45 |
--------------------------------------------------------------------------------
/examples/finance_work2.py:
--------------------------------------------------------------------------------
1 | import matplotlib.dates as mdates
2 | import matplotlib.font_manager as font_manager
3 | import matplotlib.pyplot as plt
4 | import matplotlib.ticker as mticker
5 | import numpy as np
6 | import pandas as pd
7 |
8 | ticker = 'SPY'
9 | r = pd.read_csv('data/yahoofinance-SPY-20080101-20180101.csv',
10 | index_col=0,
11 | parse_dates=True,
12 | infer_datetime_format=True)
13 |
14 |
15 | def moving_average(x, n, type='simple'):
16 | """
17 | compute an n period moving average.
18 |
19 | type is 'simple' | 'exponential'
20 |
21 | """
22 | x = np.asarray(x)
23 | if type == 'simple':
24 | weights = np.ones(n)
25 | else:
26 | weights = np.exp(np.linspace(-1., 0., n))
27 |
28 | weights /= weights.sum()
29 |
30 | a = np.convolve(x, weights, mode='full')[:len(x)]
31 | a[:n] = a[n]
32 | return a
33 |
34 |
35 | def relative_strength(prices, n=14):
36 | """
37 | compute the n period relative strength indicator
38 | http://stockcharts.com/school/doku.php?id=chart_school:glossary_r#relativestrengthindex
39 | http://www.investopedia.com/terms/r/rsi.asp
40 | """
41 |
42 | deltas = np.diff(prices)
43 | seed = deltas[:n + 1]
44 | up = seed[seed >= 0].sum() / n
45 | down = -seed[seed < 0].sum() / n
46 | rs = up / down
47 | rsi = np.zeros_like(prices)
48 | rsi[:n] = 100. - 100. / (1. + rs)
49 |
50 | for i in range(n, len(prices)):
51 | delta = deltas[i - 1] # cause the diff is 1 shorter
52 |
53 | if delta > 0:
54 | upval = delta
55 | downval = 0.
56 | else:
57 | upval = 0.
58 | downval = -delta
59 |
60 | up = (up * (n - 1) + upval) / n
61 | down = (down * (n - 1) + downval) / n
62 |
63 | rs = up / down
64 | rsi[i] = 100. - 100. / (1. + rs)
65 |
66 | return rsi
67 |
68 |
69 | def moving_average_convergence(x, nslow=26, nfast=12):
70 | """
71 | compute the MACD (Moving Average Convergence/Divergence) using a fast and
72 | slow exponential moving avg
73 |
74 | return value is emaslow, emafast, macd which are len(x) arrays
75 | """
76 | emaslow = moving_average(x, nslow, type='exponential')
77 | emafast = moving_average(x, nfast, type='exponential')
78 | return emaslow, emafast, emafast - emaslow
79 |
80 |
81 | plt.rc('axes', grid=True)
82 | plt.rc('grid', color='0.75', linestyle='-', linewidth=0.5)
83 |
84 | textsize = 9
85 | left, width = 0.1, 0.8
86 | rect1 = [left, 0.7, width, 0.2]
87 | rect2 = [left, 0.3, width, 0.4]
88 | rect3 = [left, 0.1, width, 0.2]
89 |
90 |
91 | fig = plt.figure(facecolor='white')
92 | axescolor = '#f6f6f6' # the axes background color
93 |
94 | ax1 = fig.add_axes(rect1, facecolor=axescolor) # left, bottom, width, height
95 | ax2 = fig.add_axes(rect2, facecolor=axescolor, sharex=ax1)
96 | ax2t = ax2.twinx()
97 | ax3 = fig.add_axes(rect3, facecolor=axescolor, sharex=ax1)
98 |
99 |
100 | # plot the relative strength indicator
101 | prices = r["Adj Close"]
102 | rsi = relative_strength(prices)
103 | fillcolor = 'darkgoldenrod'
104 |
105 | ax1.plot(r.index, rsi, color=fillcolor)
106 | ax1.axhline(70, color=fillcolor)
107 | ax1.axhline(30, color=fillcolor)
108 | ax1.fill_between(r.index, rsi, 70, where=(rsi >= 70),
109 | facecolor=fillcolor, edgecolor=fillcolor)
110 | ax1.fill_between(r.index, rsi, 30, where=(rsi <= 30),
111 | facecolor=fillcolor, edgecolor=fillcolor)
112 | ax1.text(0.6, 0.9, '>70 = overbought', va='top',
113 | transform=ax1.transAxes, fontsize=textsize)
114 | ax1.text(0.6, 0.1, '<30 = oversold',
115 | transform=ax1.transAxes, fontsize=textsize)
116 | ax1.set_ylim(0, 100)
117 | ax1.set_yticks([30, 70])
118 | ax1.text(0.025, 0.95, 'RSI (14)', va='top',
119 | transform=ax1.transAxes, fontsize=textsize)
120 | ax1.set_title('%s daily' % ticker)
121 |
122 | # plot the price and volume data
123 | dx = r["Adj Close"] - r.Close
124 | low = r.Low + dx
125 | high = r.High + dx
126 |
127 | deltas = np.zeros_like(prices)
128 | deltas[1:] = np.diff(prices)
129 | up = deltas > 0
130 | ax2.vlines(r.index[up], low[up], high[up], color='black', label='_nolegend_')
131 | ax2.vlines(r.index[~up], low[~up], high[~up],
132 | color='black', label='_nolegend_')
133 | ma20 = moving_average(prices, 20, type='simple')
134 | ma200 = moving_average(prices, 200, type='simple')
135 |
136 | linema20, = ax2.plot(r.index, ma20, color='blue', lw=2, label='MA (20)')
137 | linema200, = ax2.plot(r.index, ma200, color='red', lw=2, label='MA (200)')
138 |
139 | last = r.tail(1)
140 | s = '%s O:%1.2f H:%1.2f L:%1.2f C:%1.2f, V:%1.1fM Chg:%+1.2f' % (
141 | last.index.strftime('%Y.%m.%d')[0],
142 | last.Open, last.High,
143 | last.Low, last.Close,
144 | last.Volume * 1e-6,
145 | last.Close - last.Open)
146 | t4 = ax2.text(0.3, 0.9, s, transform=ax2.transAxes, fontsize=textsize)
147 |
148 | props = font_manager.FontProperties(size=10)
149 | leg = ax2.legend(loc='center left', shadow=True, fancybox=True, prop=props)
150 | leg.get_frame().set_alpha(0.5)
151 |
152 |
153 | volume = (r.Close * r.Volume) / 1e6 # dollar volume in millions
154 | vmax = volume.max()
155 | poly = ax2t.fill_between(r.index, volume, 0, label='Volume',
156 | facecolor=fillcolor, edgecolor=fillcolor)
157 | ax2t.set_ylim(0, 5 * vmax)
158 | ax2t.set_yticks([])
159 |
160 |
161 | # compute the MACD indicator
162 | fillcolor = 'darkslategrey'
163 | nslow = 26
164 | nfast = 12
165 | nema = 9
166 | emaslow, emafast, macd = moving_average_convergence(
167 | prices, nslow=nslow, nfast=nfast)
168 | ema9 = moving_average(macd, nema, type='exponential')
169 | ax3.plot(r.index, macd, color='black', lw=2)
170 | ax3.plot(r.index, ema9, color='blue', lw=1)
171 | ax3.fill_between(r.index, macd - ema9, 0, alpha=0.5,
172 | facecolor=fillcolor, edgecolor=fillcolor)
173 |
174 |
175 | ax3.text(0.025, 0.95, 'MACD (%d, %d, %d)' % (nfast, nslow, nema), va='top',
176 | transform=ax3.transAxes, fontsize=textsize)
177 |
178 | # ax3.set_yticks([])
179 | # turn off upper axis tick labels, rotate the lower ones, etc
180 | for ax in ax1, ax2, ax2t, ax3:
181 | if ax != ax3:
182 | for label in ax.get_xticklabels():
183 | label.set_visible(False)
184 | else:
185 | for label in ax.get_xticklabels():
186 | label.set_rotation(30)
187 | label.set_horizontalalignment('right')
188 |
189 | ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')
190 |
191 |
192 | class MyLocator(mticker.MaxNLocator):
193 | def __init__(self, *args, **kwargs):
194 | mticker.MaxNLocator.__init__(self, *args, **kwargs)
195 |
196 | def __call__(self, *args, **kwargs):
197 | return mticker.MaxNLocator.__call__(self, *args, **kwargs)
198 |
199 | # at most 5 ticks, pruning the upper and lower so they don't overlap
200 | # with other ticks
201 | # ax2.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both'))
202 | # ax3.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both'))
203 |
204 |
205 | ax2.yaxis.set_major_locator(MyLocator(5, prune='both'))
206 | ax3.yaxis.set_major_locator(MyLocator(5, prune='both'))
207 |
208 | plt.show()
209 |
--------------------------------------------------------------------------------
/examples/longshort.py:
--------------------------------------------------------------------------------
1 | """
2 | Illustrate the rec array utility funcitons by loading prices from a
3 | csv file, computing the daily returns, appending the results to the
4 | record arrays, joining on date
5 | """
6 | import matplotlib.mlab as mlab
7 | import matplotlib.pyplot as plt
8 | import numpy as np
9 | import pandas as pd
10 |
11 | from six.moves import urllib
12 |
13 | start_date = "2004-8-19"
14 | end_date = '2018-1-20'
15 |
16 | # grab the price data off yahoo csv quotes
17 | r1 = pd.read_csv('data/yahoofinance-AAPL-20040819-20180120.csv',
18 | index_col=0,
19 | parse_dates=True,
20 | infer_datetime_format=True)
21 | r2 = pd.read_csv('data/yahoofinance-GOOG-20040819-20180120.csv',
22 | index_col=0,
23 | parse_dates=True,
24 | infer_datetime_format=True)
25 |
26 |
27 | # compute the daily returns and add these columns to the arrays
28 | gains1 = np.zeros_like(r1["Adj Close"])
29 | gains2 = np.zeros_like(r2["Adj Close"])
30 | gains1[1:] = np.diff(r1["Adj Close"]) / r1["Adj Close"][:-1]
31 | gains2[1:] = np.diff(r2["Adj Close"]) / r2["Adj Close"][:-1]
32 | r1['gains'] = gains1
33 | r2['gains'] = gains2
34 |
35 |
36 | # now join them by date
37 | r = pd.merge(r1, r2, left_index=True, right_index=True,
38 | suffixes=(['1', '2']), sort=True)
39 |
40 |
41 | # long appl, short goog
42 | g = r.gains1 - r.gains2
43 | tr = (1 + g).cumprod() # the total return
44 |
45 | # plot the return
46 | fig, ax = plt.subplots()
47 | ax.plot(r.index, tr)
48 | ax.set_title('total return: long APPL, short GOOG')
49 | ax.grid()
50 | fig.autofmt_xdate()
51 | plt.show()
52 |
--------------------------------------------------------------------------------
/examples/plot_day_summary_oclh_demo.py:
--------------------------------------------------------------------------------
1 | """
2 | Show how to use plot_day_summary_oclh function
3 | """
4 | import matplotlib.pyplot as plt
5 | import pandas as pd
6 | from matplotlib.dates import (MONDAY, DateFormatter, MonthLocator,
7 | WeekdayLocator, date2num)
8 |
9 | from mpl_finance import plot_day_summary_oclh
10 |
11 | date1 = "2003-11-1"
12 | date2 = "2003-12-1"
13 |
14 | # every monday
15 | mondays = WeekdayLocator(MONDAY)
16 | daysFmt = DateFormatter("%d %b %y")
17 |
18 |
19 | quotes = pd.read_csv('data/yahoofinance-INTC-19950101-20040412.csv',
20 | index_col=0,
21 | parse_dates=True,
22 | infer_datetime_format=True)
23 |
24 | # select desired range of dates
25 | quotes = quotes[(quotes.index >= date1) & (quotes.index <= date2)]
26 |
27 |
28 | fig, ax = plt.subplots()
29 | plot_day_summary_oclh(ax, zip(date2num(quotes.index.to_pydatetime()),
30 | quotes['Open'], quotes['Close'],
31 | quotes['Low'], quotes['High']),
32 | ticksize=3)
33 | ax.xaxis.set_major_locator(mondays)
34 | ax.xaxis.set_major_formatter(daysFmt)
35 | ax.autoscale_view()
36 | ax.xaxis.grid(True, 'major')
37 | ax.grid(True)
38 |
39 | fig.autofmt_xdate()
40 |
41 | plt.show()
42 |
--------------------------------------------------------------------------------
/mpl_finance.py:
--------------------------------------------------------------------------------
1 | """
2 | A collection of functions for analyzing and plotting
3 | financial data. User contributions welcome!
4 |
5 | """
6 | from __future__ import (absolute_import, division, print_function,
7 | unicode_literals)
8 |
9 | import warnings as __warnings
10 | import sys as __sys
11 | if not __sys.warnoptions:
12 | import os as __os
13 | __warnings.filterwarnings("default",category=DeprecationWarning,module='mpl_finance') # Change the filter in this process
14 | __os.environ["PYTHONWARNINGS"] = "default::DeprecationWarning:mpl_finance" # Also affect subprocesses
15 |
16 | __warnings.warn('\n\n ================================================================='+
17 | '\n\n WARNING: `mpl_finance` is deprecated:'+
18 | '\n\n Please use `mplfinance` instead (no hyphen, no underscore).'+
19 | '\n\n To install: `pip install --upgrade mplfinance` '+
20 | '\n\n For more information, see: https://pypi.org/project/mplfinance/'
21 | '\n\n =================================================================\n',
22 | category=DeprecationWarning)
23 |
24 | import numpy as np
25 | from matplotlib import colors as mcolors
26 | from matplotlib.collections import LineCollection, PolyCollection
27 | from matplotlib.lines import TICKLEFT, TICKRIGHT, Line2D
28 | from matplotlib.patches import Rectangle
29 | from matplotlib.transforms import Affine2D
30 |
31 | from six.moves import xrange, zip
32 |
33 |
34 | def plot_day_summary_oclh(ax, quotes, ticksize=3,
35 | colorup='k', colordown='r'):
36 | """Plots day summary
37 |
38 | Represent the time, open, close, high, low as a vertical line
39 | ranging from low to high. The left tick is the open and the right
40 | tick is the close.
41 |
42 |
43 |
44 | Parameters
45 | ----------
46 | ax : `Axes`
47 | an `Axes` instance to plot to
48 | quotes : sequence of (time, open, close, high, low, ...) sequences
49 | data to plot. time must be in float date format - see date2num
50 | ticksize : int
51 | open/close tick marker in points
52 | colorup : color
53 | the color of the lines where close >= open
54 | colordown : color
55 | the color of the lines where close < open
56 |
57 | Returns
58 | -------
59 | lines : list
60 | list of tuples of the lines added (one tuple per quote)
61 | """
62 | return _plot_day_summary(ax, quotes, ticksize=ticksize,
63 | colorup=colorup, colordown=colordown,
64 | ochl=True)
65 |
66 |
67 | def plot_day_summary_ohlc(ax, quotes, ticksize=3,
68 | colorup='k', colordown='r'):
69 | """Plots day summary
70 |
71 | Represent the time, open, high, low, close as a vertical line
72 | ranging from low to high. The left tick is the open and the right
73 | tick is the close.
74 |
75 |
76 |
77 | Parameters
78 | ----------
79 | ax : `Axes`
80 | an `Axes` instance to plot to
81 | quotes : sequence of (time, open, high, low, close, ...) sequences
82 | data to plot. time must be in float date format - see date2num
83 | ticksize : int
84 | open/close tick marker in points
85 | colorup : color
86 | the color of the lines where close >= open
87 | colordown : color
88 | the color of the lines where close < open
89 |
90 | Returns
91 | -------
92 | lines : list
93 | list of tuples of the lines added (one tuple per quote)
94 | """
95 | return _plot_day_summary(ax, quotes, ticksize=ticksize,
96 | colorup=colorup, colordown=colordown,
97 | ochl=False)
98 |
99 |
100 | def _plot_day_summary(ax, quotes, ticksize=3,
101 | colorup='k', colordown='r',
102 | ochl=True):
103 | """Plots day summary
104 |
105 |
106 | Represent the time, open, high, low, close as a vertical line
107 | ranging from low to high. The left tick is the open and the right
108 | tick is the close.
109 |
110 |
111 |
112 | Parameters
113 | ----------
114 | ax : `Axes`
115 | an `Axes` instance to plot to
116 | quotes : sequence of quote sequences
117 | data to plot. time must be in float date format - see date2num
118 | (time, open, high, low, close, ...) vs
119 | (time, open, close, high, low, ...)
120 | set by `ochl`
121 | ticksize : int
122 | open/close tick marker in points
123 | colorup : color
124 | the color of the lines where close >= open
125 | colordown : color
126 | the color of the lines where close < open
127 | ochl: bool
128 | argument to select between ochl and ohlc ordering of quotes
129 |
130 | Returns
131 | -------
132 | lines : list
133 | list of tuples of the lines added (one tuple per quote)
134 | """
135 | # unfortunately this has a different return type than plot_day_summary2_*
136 | lines = []
137 | for q in quotes:
138 | if ochl:
139 | t, open, close, high, low = q[:5]
140 | else:
141 | t, open, high, low, close = q[:5]
142 |
143 | if close >= open:
144 | color = colorup
145 | else:
146 | color = colordown
147 |
148 | vline = Line2D(xdata=(t, t), ydata=(low, high),
149 | color=color,
150 | antialiased=False, # no need to antialias vert lines
151 | )
152 |
153 | oline = Line2D(xdata=(t, t), ydata=(open, open),
154 | color=color,
155 | antialiased=False,
156 | marker=TICKLEFT,
157 | markersize=ticksize,
158 | )
159 |
160 | cline = Line2D(xdata=(t, t), ydata=(close, close),
161 | color=color,
162 | antialiased=False,
163 | markersize=ticksize,
164 | marker=TICKRIGHT)
165 |
166 | lines.extend((vline, oline, cline))
167 | ax.add_line(vline)
168 | ax.add_line(oline)
169 | ax.add_line(cline)
170 |
171 | ax.autoscale_view()
172 |
173 | return lines
174 |
175 |
176 | def candlestick_ochl(ax, quotes, width=0.2, colorup='k', colordown='r',
177 | alpha=1.0):
178 | """
179 | Plot the time, open, close, high, low as a vertical line ranging
180 | from low to high. Use a rectangular bar to represent the
181 | open-close span. If close >= open, use colorup to color the bar,
182 | otherwise use colordown
183 |
184 | Parameters
185 | ----------
186 | ax : `Axes`
187 | an Axes instance to plot to
188 | quotes : sequence of (time, open, close, high, low, ...) sequences
189 | As long as the first 5 elements are these values,
190 | the record can be as long as you want (e.g., it may store volume).
191 |
192 | time must be in float days format - see date2num
193 |
194 | width : float
195 | fraction of a day for the rectangle width
196 | colorup : color
197 | the color of the rectangle where close >= open
198 | colordown : color
199 | the color of the rectangle where close < open
200 | alpha : float
201 | the rectangle alpha level
202 |
203 | Returns
204 | -------
205 | ret : tuple
206 | returns (lines, patches) where lines is a list of lines
207 | added and patches is a list of the rectangle patches added
208 |
209 | """
210 | return _candlestick(ax, quotes, width=width, colorup=colorup,
211 | colordown=colordown,
212 | alpha=alpha, ochl=True)
213 |
214 |
215 | def candlestick_ohlc(ax, quotes, width=0.2, colorup='k', colordown='r',
216 | alpha=1.0):
217 | """
218 | Plot the time, open, high, low, close as a vertical line ranging
219 | from low to high. Use a rectangular bar to represent the
220 | open-close span. If close >= open, use colorup to color the bar,
221 | otherwise use colordown
222 |
223 | Parameters
224 | ----------
225 | ax : `Axes`
226 | an Axes instance to plot to
227 | quotes : sequence of (time, open, high, low, close, ...) sequences
228 | As long as the first 5 elements are these values,
229 | the record can be as long as you want (e.g., it may store volume).
230 |
231 | time must be in float days format - see date2num
232 |
233 | width : float
234 | fraction of a day for the rectangle width
235 | colorup : color
236 | the color of the rectangle where close >= open
237 | colordown : color
238 | the color of the rectangle where close < open
239 | alpha : float
240 | the rectangle alpha level
241 |
242 | Returns
243 | -------
244 | ret : tuple
245 | returns (lines, patches) where lines is a list of lines
246 | added and patches is a list of the rectangle patches added
247 |
248 | """
249 | return _candlestick(ax, quotes, width=width, colorup=colorup,
250 | colordown=colordown,
251 | alpha=alpha, ochl=False)
252 |
253 |
254 | def _candlestick(ax, quotes, width=0.2, colorup='k', colordown='r',
255 | alpha=1.0, ochl=True):
256 | """
257 | Plot the time, open, high, low, close as a vertical line ranging
258 | from low to high. Use a rectangular bar to represent the
259 | open-close span. If close >= open, use colorup to color the bar,
260 | otherwise use colordown
261 |
262 | Parameters
263 | ----------
264 | ax : `Axes`
265 | an Axes instance to plot to
266 | quotes : sequence of quote sequences
267 | data to plot. time must be in float date format - see date2num
268 | (time, open, high, low, close, ...) vs
269 | (time, open, close, high, low, ...)
270 | set by `ochl`
271 | width : float
272 | fraction of a day for the rectangle width
273 | colorup : color
274 | the color of the rectangle where close >= open
275 | colordown : color
276 | the color of the rectangle where close < open
277 | alpha : float
278 | the rectangle alpha level
279 | ochl: bool
280 | argument to select between ochl and ohlc ordering of quotes
281 |
282 | Returns
283 | -------
284 | ret : tuple
285 | returns (lines, patches) where lines is a list of lines
286 | added and patches is a list of the rectangle patches added
287 |
288 | """
289 |
290 | OFFSET = width / 2.0
291 |
292 | lines = []
293 | patches = []
294 | for q in quotes:
295 | if ochl:
296 | t, open, close, high, low = q[:5]
297 | else:
298 | t, open, high, low, close = q[:5]
299 |
300 | if close >= open:
301 | color = colorup
302 | lower = open
303 | height = close - open
304 | else:
305 | color = colordown
306 | lower = close
307 | height = open - close
308 |
309 | vline = Line2D(
310 | xdata=(t, t), ydata=(low, high),
311 | color=color,
312 | linewidth=0.5,
313 | antialiased=True,
314 | )
315 |
316 | rect = Rectangle(
317 | xy=(t - OFFSET, lower),
318 | width=width,
319 | height=height,
320 | facecolor=color,
321 | edgecolor=color,
322 | )
323 | rect.set_alpha(alpha)
324 |
325 | lines.append(vline)
326 | patches.append(rect)
327 | ax.add_line(vline)
328 | ax.add_patch(rect)
329 | ax.autoscale_view()
330 |
331 | return lines, patches
332 |
333 |
334 | def _check_input(opens, closes, highs, lows, miss=-1):
335 | """Checks that *opens*, *highs*, *lows* and *closes* have the same length.
336 | NOTE: this code assumes if any value open, high, low, close is
337 | missing (*-1*) they all are missing
338 |
339 | Parameters
340 | ----------
341 | ax : `Axes`
342 | an Axes instance to plot to
343 | opens : sequence
344 | sequence of opening values
345 | highs : sequence
346 | sequence of high values
347 | lows : sequence
348 | sequence of low values
349 | closes : sequence
350 | sequence of closing values
351 | miss : int
352 | identifier of the missing data
353 |
354 | Raises
355 | ------
356 | ValueError
357 | if the input sequences don't have the same length
358 | """
359 |
360 | def _missing(sequence, miss=-1):
361 | """Returns the index in *sequence* of the missing data, identified by
362 | *miss*
363 |
364 | Parameters
365 | ----------
366 | sequence :
367 | sequence to evaluate
368 | miss :
369 | identifier of the missing data
370 |
371 | Returns
372 | -------
373 | where_miss: numpy.ndarray
374 | indices of the missing data
375 | """
376 | return np.where(np.array(sequence) == miss)[0]
377 |
378 | same_length = len(opens) == len(highs) == len(lows) == len(closes)
379 | _missopens = _missing(opens)
380 | same_missing = ((_missopens == _missing(highs)).all() and
381 | (_missopens == _missing(lows)).all() and
382 | (_missopens == _missing(closes)).all())
383 |
384 | if not (same_length and same_missing):
385 | msg = ("*opens*, *highs*, *lows* and *closes* must have the same"
386 | " length. NOTE: this code assumes if any value open, high,"
387 | " low, close is missing (*-1*) they all must be missing.")
388 | raise ValueError(msg)
389 |
390 |
391 | def plot_day_summary2_ochl(ax, opens, closes, highs, lows, ticksize=4,
392 | colorup='k', colordown='r'):
393 | """Represent the time, open, close, high, low, as a vertical line
394 | ranging from low to high. The left tick is the open and the right
395 | tick is the close.
396 |
397 | Parameters
398 | ----------
399 | ax : `Axes`
400 | an Axes instance to plot to
401 | opens : sequence
402 | sequence of opening values
403 | closes : sequence
404 | sequence of closing values
405 | highs : sequence
406 | sequence of high values
407 | lows : sequence
408 | sequence of low values
409 | ticksize : int
410 | size of open and close ticks in points
411 | colorup : color
412 | the color of the lines where close >= open
413 | colordown : color
414 | the color of the lines where close < open
415 |
416 | Returns
417 | -------
418 | ret : list
419 | a list of lines added to the axes
420 | """
421 |
422 | return plot_day_summary2_ohlc(ax, opens, highs, lows, closes, ticksize,
423 | colorup, colordown)
424 |
425 |
426 | def plot_day_summary2_ohlc(ax, opens, highs, lows, closes, ticksize=4,
427 | colorup='k', colordown='r'):
428 | """Represent the time, open, high, low, close as a vertical line
429 | ranging from low to high. The left tick is the open and the right
430 | tick is the close.
431 | *opens*, *highs*, *lows* and *closes* must have the same length.
432 | NOTE: this code assumes if any value open, high, low, close is
433 | missing (*-1*) they all are missing
434 |
435 | Parameters
436 | ----------
437 | ax : `Axes`
438 | an Axes instance to plot to
439 | opens : sequence
440 | sequence of opening values
441 | highs : sequence
442 | sequence of high values
443 | lows : sequence
444 | sequence of low values
445 | closes : sequence
446 | sequence of closing values
447 | ticksize : int
448 | size of open and close ticks in points
449 | colorup : color
450 | the color of the lines where close >= open
451 | colordown : color
452 | the color of the lines where close < open
453 |
454 | Returns
455 | -------
456 | ret : list
457 | a list of lines added to the axes
458 | """
459 |
460 | _check_input(opens, highs, lows, closes)
461 |
462 | rangeSegments = [((i, low), (i, high)) for i, low, high in
463 | zip(xrange(len(lows)), lows, highs) if low != -1]
464 |
465 | # the ticks will be from ticksize to 0 in points at the origin and
466 | # we'll translate these to the i, close location
467 | openSegments = [((-ticksize, 0), (0, 0))]
468 |
469 | # the ticks will be from 0 to ticksize in points at the origin and
470 | # we'll translate these to the i, close location
471 | closeSegments = [((0, 0), (ticksize, 0))]
472 |
473 | offsetsOpen = [(i, open) for i, open in
474 | zip(xrange(len(opens)), opens) if open != -1]
475 |
476 | offsetsClose = [(i, close) for i, close in
477 | zip(xrange(len(closes)), closes) if close != -1]
478 |
479 | scale = ax.figure.dpi * (1.0 / 72.0)
480 |
481 | tickTransform = Affine2D().scale(scale, 0.0)
482 |
483 | colorup = mcolors.to_rgba(colorup)
484 | colordown = mcolors.to_rgba(colordown)
485 | colord = {True: colorup, False: colordown}
486 | colors = [colord[open < close] for open, close in
487 | zip(opens, closes) if open != -1 and close != -1]
488 |
489 | useAA = 0, # use tuple here
490 | lw = 1, # and here
491 | rangeCollection = LineCollection(rangeSegments,
492 | colors=colors,
493 | linewidths=lw,
494 | antialiaseds=useAA,
495 | )
496 |
497 | openCollection = LineCollection(openSegments,
498 | colors=colors,
499 | antialiaseds=useAA,
500 | linewidths=lw,
501 | offsets=offsetsOpen,
502 | transOffset=ax.transData,
503 | )
504 | openCollection.set_transform(tickTransform)
505 |
506 | closeCollection = LineCollection(closeSegments,
507 | colors=colors,
508 | antialiaseds=useAA,
509 | linewidths=lw,
510 | offsets=offsetsClose,
511 | transOffset=ax.transData,
512 | )
513 | closeCollection.set_transform(tickTransform)
514 |
515 | minpy, maxx = (0, len(rangeSegments))
516 | miny = min([low for low in lows if low != -1])
517 | maxy = max([high for high in highs if high != -1])
518 | corners = (minpy, miny), (maxx, maxy)
519 | ax.update_datalim(corners)
520 | ax.autoscale_view()
521 |
522 | # add these last
523 | ax.add_collection(rangeCollection)
524 | ax.add_collection(openCollection)
525 | ax.add_collection(closeCollection)
526 | return rangeCollection, openCollection, closeCollection
527 |
528 |
529 | def candlestick2_ochl(ax, opens, closes, highs, lows, width=4,
530 | colorup='k', colordown='r',
531 | alpha=0.75):
532 | """Represent the open, close as a bar line and high low range as a
533 | vertical line.
534 |
535 | Preserves the original argument order.
536 |
537 |
538 | Parameters
539 | ----------
540 | ax : `Axes`
541 | an Axes instance to plot to
542 | opens : sequence
543 | sequence of opening values
544 | closes : sequence
545 | sequence of closing values
546 | highs : sequence
547 | sequence of high values
548 | lows : sequence
549 | sequence of low values
550 | width : int
551 | size of open and close ticks in points
552 | colorup : color
553 | the color of the lines where close >= open
554 | colordown : color
555 | the color of the lines where close < open
556 | alpha : float
557 | bar transparency
558 |
559 | Returns
560 | -------
561 | ret : tuple
562 | (lineCollection, barCollection)
563 | """
564 |
565 | return candlestick2_ohlc(ax, opens, highs, lows, closes, width=width,
566 | colorup=colorup, colordown=colordown,
567 | alpha=alpha)
568 |
569 |
570 | def candlestick2_ohlc(ax, opens, highs, lows, closes, width=4,
571 | colorup='k', colordown='r',
572 | alpha=0.75):
573 | """Represent the open, close as a bar line and high low range as a
574 | vertical line.
575 |
576 | NOTE: this code assumes if any value open, low, high, close is
577 | missing they all are missing
578 |
579 |
580 | Parameters
581 | ----------
582 | ax : `Axes`
583 | an Axes instance to plot to
584 | opens : sequence
585 | sequence of opening values
586 | highs : sequence
587 | sequence of high values
588 | lows : sequence
589 | sequence of low values
590 | closes : sequence
591 | sequence of closing values
592 | width : int
593 | size of open and close ticks in points
594 | colorup : color
595 | the color of the lines where close >= open
596 | colordown : color
597 | the color of the lines where close < open
598 | alpha : float
599 | bar transparency
600 |
601 | Returns
602 | -------
603 | ret : tuple
604 | (lineCollection, barCollection)
605 | """
606 |
607 | _check_input(opens, highs, lows, closes)
608 |
609 | delta = width / 2.
610 | barVerts = [((i - delta, open),
611 | (i - delta, close),
612 | (i + delta, close),
613 | (i + delta, open))
614 | for i, open, close in zip(xrange(len(opens)), opens, closes)
615 | if open != -1 and close != -1]
616 |
617 | rangeSegments = [((i, low), (i, high))
618 | for i, low, high in zip(xrange(len(lows)), lows, highs)
619 | if low != -1]
620 |
621 | colorup = mcolors.to_rgba(colorup, alpha)
622 | colordown = mcolors.to_rgba(colordown, alpha)
623 | colord = {True: colorup, False: colordown}
624 | colors = [colord[open < close]
625 | for open, close in zip(opens, closes)
626 | if open != -1 and close != -1]
627 |
628 | useAA = 0, # use tuple here
629 | lw = 0.5, # and here
630 | rangeCollection = LineCollection(rangeSegments,
631 | colors=colors,
632 | linewidths=lw,
633 | antialiaseds=useAA,
634 | )
635 |
636 | barCollection = PolyCollection(barVerts,
637 | facecolors=colors,
638 | edgecolors=colors,
639 | antialiaseds=useAA,
640 | linewidths=lw,
641 | )
642 |
643 | minx, maxx = 0, len(rangeSegments)
644 | miny = min([low for low in lows if low != -1])
645 | maxy = max([high for high in highs if high != -1])
646 |
647 | corners = (minx, miny), (maxx, maxy)
648 | ax.update_datalim(corners)
649 | ax.autoscale_view()
650 |
651 | # add these last
652 | ax.add_collection(rangeCollection)
653 | ax.add_collection(barCollection)
654 | return rangeCollection, barCollection
655 |
656 |
657 | def volume_overlay(ax, opens, closes, volumes,
658 | colorup='k', colordown='r',
659 | width=4, alpha=1.0):
660 | """Add a volume overlay to the current axes. The opens and closes
661 | are used to determine the color of the bar. -1 is missing. If a
662 | value is missing on one it must be missing on all
663 |
664 | Parameters
665 | ----------
666 | ax : `Axes`
667 | an Axes instance to plot to
668 | opens : sequence
669 | a sequence of opens
670 | closes : sequence
671 | a sequence of closes
672 | volumes : sequence
673 | a sequence of volumes
674 | width : int
675 | the bar width in points
676 | colorup : color
677 | the color of the lines where close >= open
678 | colordown : color
679 | the color of the lines where close < open
680 | alpha : float
681 | bar transparency
682 |
683 | Returns
684 | -------
685 | ret : `barCollection`
686 | The `barrCollection` added to the axes
687 |
688 | """
689 |
690 | colorup = mcolors.to_rgba(colorup, alpha)
691 | colordown = mcolors.to_rgba(colordown, alpha)
692 | colord = {True: colorup, False: colordown}
693 | colors = [colord[open < close]
694 | for open, close in zip(opens, closes)
695 | if open != -1 and close != -1]
696 |
697 | delta = width / 2.
698 | bars = [((i - delta, 0), (i - delta, v), (i + delta, v), (i + delta, 0))
699 | for i, v in enumerate(volumes)
700 | if v != -1]
701 |
702 | barCollection = PolyCollection(bars,
703 | facecolors=colors,
704 | edgecolors=((0, 0, 0, 1), ),
705 | antialiaseds=(0,),
706 | linewidths=(0.5,),
707 | )
708 |
709 | ax.add_collection(barCollection)
710 | corners = (0, 0), (len(bars), max(volumes))
711 | ax.update_datalim(corners)
712 | ax.autoscale_view()
713 |
714 | # add these last
715 | return barCollection
716 |
717 |
718 | def volume_overlay2(ax, closes, volumes,
719 | colorup='k', colordown='r',
720 | width=4, alpha=1.0):
721 | """
722 | Add a volume overlay to the current axes. The closes are used to
723 | determine the color of the bar. -1 is missing. If a value is
724 | missing on one it must be missing on all
725 |
726 | nb: first point is not displayed - it is used only for choosing the
727 | right color
728 |
729 |
730 | Parameters
731 | ----------
732 | ax : `Axes`
733 | an Axes instance to plot to
734 | closes : sequence
735 | a sequence of closes
736 | volumes : sequence
737 | a sequence of volumes
738 | width : int
739 | the bar width in points
740 | colorup : color
741 | the color of the lines where close >= open
742 | colordown : color
743 | the color of the lines where close < open
744 | alpha : float
745 | bar transparency
746 |
747 | Returns
748 | -------
749 | ret : `barCollection`
750 | The `barrCollection` added to the axes
751 |
752 | """
753 |
754 | return volume_overlay(ax, closes[:-1], closes[1:], volumes[1:],
755 | colorup, colordown, width, alpha)
756 |
757 |
758 | def volume_overlay3(ax, quotes,
759 | colorup='k', colordown='r',
760 | width=4, alpha=1.0):
761 | """Add a volume overlay to the current axes. quotes is a list of (d,
762 | open, high, low, close, volume) and close-open is used to
763 | determine the color of the bar
764 |
765 | Parameters
766 | ----------
767 | ax : `Axes`
768 | an Axes instance to plot to
769 | quotes : sequence of (time, open, high, low, close, ...) sequences
770 | data to plot. time must be in float date format - see date2num
771 | width : int
772 | the bar width in points
773 | colorup : color
774 | the color of the lines where close1 >= close0
775 | colordown : color
776 | the color of the lines where close1 < close0
777 | alpha : float
778 | bar transparency
779 |
780 | Returns
781 | -------
782 | ret : `barCollection`
783 | The `barrCollection` added to the axes
784 |
785 |
786 | """
787 |
788 | colorup = mcolors.to_rgba(colorup, alpha)
789 | colordown = mcolors.to_rgba(colordown, alpha)
790 | colord = {True: colorup, False: colordown}
791 |
792 | dates, opens, highs, lows, closes, volumes = list(zip(*quotes))
793 | colors = [colord[close1 >= close0]
794 | for close0, close1 in zip(closes[:-1], closes[1:])
795 | if close0 != -1 and close1 != -1]
796 | colors.insert(0, colord[closes[0] >= opens[0]])
797 |
798 | right = width / 2.0
799 | left = -width / 2.0
800 |
801 | bars = [((left, 0), (left, volume), (right, volume), (right, 0))
802 | for d, open, high, low, close, volume in quotes]
803 |
804 | sx = ax.figure.dpi * (1.0 / 72.0) # scale for points
805 | sy = ax.bbox.height / ax.viewLim.height
806 |
807 | barTransform = Affine2D().scale(sx, sy)
808 |
809 | dates = [d for d, open, high, low, close, volume in quotes]
810 | offsetsBars = [(d, 0) for d in dates]
811 |
812 | useAA = 0, # use tuple here
813 | lw = 0.5, # and here
814 | barCollection = PolyCollection(bars,
815 | facecolors=colors,
816 | edgecolors=((0, 0, 0, 1),),
817 | antialiaseds=useAA,
818 | linewidths=lw,
819 | offsets=offsetsBars,
820 | transOffset=ax.transData,
821 | )
822 | barCollection.set_transform(barTransform)
823 |
824 | minpy, maxx = (min(dates), max(dates))
825 | miny = 0
826 | maxy = max([volume for d, open, high, low, close, volume in quotes])
827 | corners = (minpy, miny), (maxx, maxy)
828 | ax.update_datalim(corners)
829 | # print 'datalim', ax.dataLim.bounds
830 | # print 'viewlim', ax.viewLim.bounds
831 |
832 | ax.add_collection(barCollection)
833 | ax.autoscale_view()
834 |
835 | return barCollection
836 |
837 |
838 | def index_bar(ax, vals,
839 | facecolor='b', edgecolor='l',
840 | width=4, alpha=1.0, ):
841 | """Add a bar collection graph with height vals (-1 is missing).
842 |
843 | Parameters
844 | ----------
845 | ax : `Axes`
846 | an Axes instance to plot to
847 | vals : sequence
848 | a sequence of values
849 | facecolor : color
850 | the color of the bar face
851 | edgecolor : color
852 | the color of the bar edges
853 | width : int
854 | the bar width in points
855 | alpha : float
856 | bar transparency
857 |
858 | Returns
859 | -------
860 | ret : `barCollection`
861 | The `barrCollection` added to the axes
862 |
863 | """
864 |
865 | facecolors = (mcolors.to_rgba(facecolor, alpha),)
866 | edgecolors = (mcolors.to_rgba(edgecolor, alpha),)
867 |
868 | right = width / 2.0
869 | left = -width / 2.0
870 |
871 | bars = [((left, 0), (left, v), (right, v), (right, 0))
872 | for v in vals if v != -1]
873 |
874 | sx = ax.figure.dpi * (1.0 / 72.0) # scale for points
875 | sy = ax.bbox.height / ax.viewLim.height
876 |
877 | barTransform = Affine2D().scale(sx, sy)
878 |
879 | offsetsBars = [(i, 0) for i, v in enumerate(vals) if v != -1]
880 |
881 | barCollection = PolyCollection(bars,
882 | facecolors=facecolors,
883 | edgecolors=edgecolors,
884 | antialiaseds=(0,),
885 | linewidths=(0.5,),
886 | offsets=offsetsBars,
887 | transOffset=ax.transData,
888 | )
889 | barCollection.set_transform(barTransform)
890 |
891 | minpy, maxx = (0, len(offsetsBars))
892 | miny = 0
893 | maxy = max([v for v in vals if v != -1])
894 | corners = (minpy, miny), (maxx, maxy)
895 | ax.update_datalim(corners)
896 | ax.autoscale_view()
897 |
898 | # add these last
899 | ax.add_collection(barCollection)
900 | return barCollection
901 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 | with open('README.md') as f:
4 | long_description = f.read()
5 |
6 | setup(name='mpl_finance',
7 | version='0.10.1',
8 | author='MPL Developers',
9 | author_email='matplotlib-users@python.org',
10 | py_modules=['mpl_finance'],
11 | description='Finance plots using matplotlib',
12 | long_description=long_description,
13 | long_description_content_type='text/markdown; charset=UTF-8',
14 | url='http://github.com/matplotlib/mpl-finance',
15 | platforms='Cross platform (Linux, Mac OSX, Windows)',
16 | install_requires=['matplotlib'],
17 | license="BSD-style",
18 | classifiers=['Development Status :: 7 - Inactive',
19 | 'Programming Language :: Python :: 2',
20 | 'Programming Language :: Python :: 2.7',
21 | 'Programming Language :: Python :: 3',
22 | 'Programming Language :: Python :: 3.3',
23 | 'Programming Language :: Python :: 3.4',
24 | 'Programming Language :: Python :: 3.5',
25 | 'Programming Language :: Python :: 3.6',
26 | ],
27 | keywords='finance',
28 | )
29 |
--------------------------------------------------------------------------------
/tests.py:
--------------------------------------------------------------------------------
1 | import glob
2 | import os
3 | import subprocess
4 |
5 |
6 | def test_e2e_examples():
7 | """Run e2e tests over examples folder"""
8 | os.chdir("examples")
9 | exs = glob.glob('*.py')
10 | for ex in exs:
11 | subprocess.check_call(["python", ex])
12 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | # Tox (http://tox.testrun.org/) is a tool for running tests
2 | # in multiple virtualenvs. This configuration file will run the
3 | # test suite on all supported python versions. To use it, "pip install tox"
4 | # and then run "tox" from this directory.
5 |
6 | [tox]
7 | envlist = py36, py37, py38
8 | [pytest]
9 | python_files = 'tests.py'
10 |
11 | [testenv]
12 | deps =
13 | matplotlib
14 | numpy
15 | pandas
16 | pytest
17 | setenv =
18 | # don't use interactive backend for matplotlib in e2e tests
19 | MPLBACKEND = agg
20 | commands =
21 | pytest
22 |
--------------------------------------------------------------------------------