fmilthaler / finquant Goto Github PK
View Code? Open in Web Editor NEWA program for financial portfolio management, analysis and optimisation.
License: MIT License
A program for financial portfolio management, analysis and optimisation.
License: MIT License
When using yfinance as the data source no data is returned.
In portfolio.py line 791
start_date = datetime.datetime.strptime(end_date, "%Y-%m-%d")
Hey thanks so much for all your work here! It is really useful for me.
The plots look particularly great. My question is, is there a way to get the EF plot to also show the "black line" that defines the efficient frontier? It shows that in your example picture in ReadMe but not in the plot that is actually generated. Very minor, really for aesthetics sake. Thank you so much! :)
Finally set up pylint for this project
Hi
I do have a portfolio where some of the stocks have data starting at different time (some are more recent). I build my own Dataframe, so it's made to have an index that is date, and then if one stock still has no data when another one has, for that date the value for the stock still not started will be 0.0.
I then use FinQuant, giving it my Dataframe with the stocks and another with the weights, and do all calculations I need.
It works in every aspects I use, and I use pretty much all the functions, but one function, comp_cumulative_returns() fails to deal correctly with the data. If one of the stocks in portfolio starts later than the others, and so in the dataframe the prices for that stock are 0.0 till the 'real' data starts, that function doesn't work and the resulting output has 0.0 for the whole sequence of that specific stock.
Any hint about how to deal with this case?
Some of the new classes, e.g. market and asset are currently not in the documentation
When you are bored... Redo documentation to include proper support for type hints (after type hints are consistently implemented and tested with mypy).
In some places, df.loc[i] is used, when it should be df.iloc[i].
Failed pipeline: https://github.com/fmilthaler/FinQuant/actions/runs/5730526086/job/15530536877?pr=120
- name: Check out code
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
the above causes the failure. the below works on forks:
- name: Checkout code
uses: actions/checkout@v3
Implement support for yahoo finance alongside quandl
Congratulations for the work. Excellent library!
How to use the efficient frontier data to plot in the plotly library the EF Min Volatility and EF Max Sharpe Ratio?
Thanks
... not pandas.DataFrame.
Hi there,
Tried to download the stock price from yfinance, used the code snippest in documentation.
from finquant.portfolio import build_portfolio
names = ['GOOG', 'AMZN', 'MCD', 'DIS']
pf = build_portfolio(names=names, data_api="yfinance")
But once I run it, it says 'AttributeError: 'Index' object has no attribute 'tz_localize''
Thanks in advance.
Hi Sir,
I have just started with Python and cam across the FinQuant documentation. Was successful in replicating the code for stocks, but when i am trying to use S&P, FTSE and Nikkei in place of stocks then i receive an error. So could help me with the issue.
Example to show how to manually add stock(s) to a previously created instance of Portfolio.
... and mypy could be added at a later stage
getting error when i run the commend
pf = build_portfolio(names=['GOOG', 'AMZN'],
start_date=start_date,
end_date=end_date)
Exception: Error during download of stock data from Quandl.
Make sure all the requested stock names/tickers are supported by Quandl.
Kindly solve the issue
Hello @fmilthaler !
I'm having some dificulty to use ef_maximum_sharpe_ratio with a more "spreaded" allocation... Would it be possible to add some regularization function to avoid the optimizer to concentrate allocation in only 1 or 2 stocks?
Another way to resolve this could be to add some "per stock" or global limit settings (lower and upper). I don't know wich solution is better.... E.g: only allow a maximum of 80% of portfolio allocation for each stock.
Thanks!
When running this code, that was extracted from the examples of the documentation, the plot seems to be inverted and since i simply copied/pasted the code i really dont know what would go wrong.
``#%%
from finquant.portfolio import build_portfolio
names = ['GOOG', 'AMZN', 'MCD', 'DIS']
pf = build_portfolio(names=names, data_api="yfinance")
from finquant.moving_average import compute_ma, ema
dis = pf.get_stock("DIS").data.copy(deep=True)
spans = [10, 50, 100, 150]
ma = compute_ma(dis, ema, spans, plot=True)
print(ma.tail())`
`
see if this should/could be implemented.
Causes: tests to fail with pandas (panda.core now PRIVATE).
Dear hero's
Im using your libary heavly but now there is a problem: this error keeps popping up:
\finquant\monte_carlo.py:37: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
return np.asarray(result)
Are you still alive? Is there a possiblity for you to fix this?
Can I fix it?
I'm currently having an issue running the demo code when I try to run the mc_optimisation with 3 stocks in the portfolio. I've tried running with 2 stocks as well as portfolios with more than 3 stocks and everything seems to work fine. However, when I setup a portfolio with 3 stocks, I run into the following error.
ValueError: Shape of passed values is (2, 5000), indices imply (2, 3)
Code that produced the error:
from finquant.portfolio import build_portfolio
names = ['MSFT', 'AAPL', 'GOOG']
start_date = '2015-01-01'
end_date = '2020-04-25'
pf = build_portfolio(names=names,
start_date=start_date,
end_date=end_date, data_api="yfinance")
opt_w, opt_res = pf.mc_optimisation(num_trials=5000)
Thanks for the great work at this library.
How can I set the lower and upper limit for the allocation of shares in the portfolio when calculating EfficientFrontier? E.g. not less than 2% and not more than 15% per title.
Thank you
Mira
As part of that: where a variable could be either pd.Series
or pd.DataFrame
, do sth like the following:
DataFrameOrSeries = Union[pd.DataFrame, pd.Series]
def compute_ma(
data: DataFrameOrSeries, fun: Callable, spans: List[int], plot: bool = True
) -> pd.DataFrame:
# rest of function
While at it, fix pylint issues as well.
Adding "MC" or "Monte-Carlo" to labels of Monte Carlo optimisation plots. Easier to distinguish it from the Efficient Frontier output.
First of all thanks for the great work. This package is amazing!
I think apart from moving averages and related bollinger bands, indicators like RSI would add relative strength to the package (pun intended). Let me know what you think.
This issue is about adding a feature for plotting RSI indicators using a 14 day window as suggested using the approach here -> https://www.alpharithms.com/relative-strength-index-rsi-in-python-470209/
Update: Edited the issue and generalized it over a number of momentum indicators. I can go ahead and implement them all or we can discuss it if you have suggestions.
Hello Frank,
Awesome job on Finquant. I was trying to use however, I myself am new to finance. I had a question.
The allocation column in a portfolio. Are they number of units of stocks? or are they weighted?
also. How do I input what is my average price for which i bought these stocks?
Sorry had to ask you via issues since there was not other way to contact. you.
Thanks for your help
Regards
Sriram
I noticed when adding a number of stocks to a portfolio the time to add them takes longer and longer. Adding a deferment to the pf._update() call seems to resolve this and makes adding bulk stocks much faster. Pull request to follow for your consideration.
Error while using package
-packages\finquant\portfolio.py:260: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
self.portfolio = self.portfolio.append(stock.investmentinfo, ignore_index=True)
Cant this problem be solved.
Implementation
Hi @fmilthaler / @PietropaoloFrisoni,
When you guys get the time, could you add some unit tests for the monte_carlo and efficient_frontier modules? I feel that these are as essential as the portfolio file. Understanding the effect of changes to preserving the functionality could be made clearer through a few more comprehensive unit tests.
Thanks for your continued hard work.
Hi
I'm exploring Finquant as it seems really the best library out there for quick portfolio optimisation.
I'm testing it following the examples for csv files, it works with the test provided .csv, when I try with my ones I can create a portfolio equally balanced without problems (so without providing the weights from portfolio.csv), but when I try giving custom weights I receive error:
ValueError Traceback (most recent call last)
in
50 print(df_data)
51
---> 52 pf = build_portfolio(data=df_data, pf_allocation=df_pf)
53 #pf = build_portfolio(data=df_data)
54
/usr/local/lib/python3.7/site-packages/finquant/portfolio.py in build_portfolio(**kwargs)
1181 )
1182 # get portfolio:
-> 1183 pf = _build_portfolio_from_df(**kwargs)
1184
1185 # final check
/usr/local/lib/python3.7/site-packages/finquant/portfolio.py in _build_portfolio_from_df(data, pf_allocation, datacolumns)
1037 # extract only "Adjusted Close" price ("Adj. Close" in quandl, "Adj Close" in yfinance)
1038 # column from DataFrame:
-> 1039 data = _get_stocks_data_columns(data, pf_allocation.Name.values, datacolumns)
1040 # building portfolio:
1041 pf = Portfolio()
/usr/local/lib/python3.7/site-packages/finquant/portfolio.py in _get_stocks_data_columns(data, names, cols)
875 # else, error
876 else:
--> 877 raise ValueError("Could not find column labels in given dataframe.")
878 # append correct name to list of correct names
879 reqcolnames.append(colname)
ValueError: Could not find column labels in given dataframe.
I've tried looking into portfolio.py to see why I get the error with my .csv only, but I can't see honestly where is the problem.
This is my stocks file containing the close prices (it works):
EQQQ float64
IWFM float64
IGLT float64
IBTM float64
SGLN float64
STM float64
dtype: object
EQQQ IWFM IGLT IBTM SGLN STM
Date
2015-01-02 6721.0 1694.75 12.44 128.51 1532.5 246.4
2015-01-05 6713.0 1690.25 12.51 130.25 1554.5 242.0
2015-01-06 6670.0 1684.75 12.61 131.75 1579.0 241.5
2015-01-07 6724.0 1706.00 12.58 132.54 1597.5 245.1
2015-01-08 6866.0 1740.00 12.55 131.73 1593.0 252.7
And this is my portfolio.csv containing the weights:
Allocation float64
Name object
dtype: object
Allocation Name
0 20.25 EQQQ
1 10.97 IWFM
2 29.44 IGLT
3 28.56 IBTM
4 9.67 SGLN
5 1.11 SMT
Any idea how can I make it work and what's the problem? As I said it works with test data CSV in your repo...
`import os
import numpy as np
import pandas as pd
from finquant.portfolio import build_portfolio
from finquant.moving_average import compute_ma, ema
names = ['GOOG', 'AMZN', 'MCD', 'DIS']
pf = build_portfolio(names=names, data_api="yfinance")
dis = pf.get_stock("DIS").data.copy(deep=True)
spans = [10, 50, 100, 150, 200]
ma = compute_ma(dis, ema, spans, plot=True)
print(ma.tail())
`
`ssh://leef_wsl_u18@localhost:22/home/leef_wsl_u18/miniconda3/envs/py36/bin/python -u /home/leef_wsl_u18/.pycharm_helpers/pydev/pydevd.py --cmd-line --multiproc --qt-support=auto --client 0.0.0.0 --port 55053 --file /tmp/rd_finquant/rd_leef/rd2.py
Connected to pydev debugger (build 211.7142.13)
[100%**] 4 of 4 completed
Traceback (most recent call last):
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/contextlib.py", line 99, in exit
self.gen.throw(type, value, traceback)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/plotting/_matplotlib/converter.py", line 85, in pandas_converters
yield
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/plotting/_matplotlib/converter.py", line 65, in wrapper
return func(*args, **kwargs)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/plotting/_matplotlib/core.py", line 668, in _plot
return ax.plot(*args, **kwds)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/init.py", line 1892, in inner
return func(ax, *args, **kwargs)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/axes/_axes.py", line 1407, in plot
self.add_line(line)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/axes/_base.py", line 1787, in add_line
self._update_line_limits(line)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/axes/_base.py", line 1809, in _update_line_limits
path = line.get_path()
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/lines.py", line 989, in get_path
self.recache()
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/lines.py", line 672, in recache
xconv = self.convert_xunits(self._xorig)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/artist.py", line 199, in convert_xunits
return ax.xaxis.convert_units(x)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/axis.py", line 1472, in convert_units
ret = self.converter.convert(x, self.units, self)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/plotting/_matplotlib/converter.py", line 256, in convert
values = DatetimeConverter._convert_1d(values, unit, axis)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/plotting/_matplotlib/converter.py", line 291, in _convert_1d
values = dates.date2num(values)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/dates.py", line 362, in date2num
return _to_ordinalf_np_vectorized(d)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/numpy/lib/function_base.py", line 2108, in call
return self._vectorize_call(func=func, args=vargs)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/numpy/lib/function_base.py", line 2186, in _vectorize_call
ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/numpy/lib/function_base.py", line 2146, in _get_ufunc_and_otypes
outputs = func(*inputs)
File "/home/leef_wsl_u18/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/dates.py", line 220, in _to_ordinalf
python-BaseException
base = float(dt.toordinal())
AttributeError: 'numpy.datetime64' object has no attribute 'toordinal'
Process finished with exit code 1
`
Run both mypy and pylint on the code base and (slowly) fix issues
When trying to get data from Quandl I get the an error (made sure ticker names are correct beforehand):
`d = {
0: {"Name": "XLON/BP_", "Allocation": 1000000},
1: {"Name": "XLON/III", "Allocation": 1000000},
2: {"Name": "XLON/GSK", "Allocation": 1000000},
3: {"Name": "XLON/OCDO", "Allocation": 1000000},
4: {"Name": "XLON/RBS", "Allocation": 2000000},
5: {"Name": "XLON/SVT", "Allocation": 1000000},
}
pf_allocation = pd.DataFrame.from_dict(d, orient="index")
#set list of names based on names
names = pf_allocation["Name"].values.tolist()`
This is the error message:
`runfile('C:/Users/Joe Shiafa Pierce/.spyder-py3/FinQuant POM project.py', wdir='C:/Users/Joe Shiafa Pierce/.spyder-py3')
Traceback (most recent call last):
File "", line 1, in
runfile('C:/Users/Joe Shiafa Pierce/.spyder-py3/FinQuant POM project.py', wdir='C:/Users/Joe Shiafa Pierce/.spyder-py3')
File "C:\Users\Joe Shiafa Pierce\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 786, in runfile
execfile(filename, namespace)
File "C:\Users\Joe Shiafa Pierce\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/Joe Shiafa Pierce/.spyder-py3/FinQuant POM project.py", line 40, in
names=names, pf_allocation=pf_allocation, start_date=start, end_date=end
File "C:\Users\Joe Shiafa Pierce\Anaconda3\lib\site-packages\finquant\portfolio.py", line 1153, in build_portfolio
pf = _build_portfolio_from_api(**kwargs)
File "C:\Users\Joe Shiafa Pierce\Anaconda3\lib\site-packages\finquant\portfolio.py", line 935, in _build_portfolio_from_api
pf = _build_portfolio_from_df(data, pf_allocation)
File "C:\Users\Joe Shiafa Pierce\Anaconda3\lib\site-packages\finquant\portfolio.py", line 1035, in _build_portfolio_from_df
data = _get_stocks_data_columns(data, pf_allocation.Name.values, datacolumns)
File "C:\Users\Joe Shiafa Pierce\Anaconda3\lib\site-packages\finquant\portfolio.py", line 869, in _get_stocks_data_columns
raise ValueError("Could not find column labels in given dataframe.")
ValueError: Could not find column labels in given dataframe.`
Thanks for your help,
Hi @fmilthaler and @PietropaoloFrisoni
Is there a way to compare the effectiveness of this program to a benchmarked or baseline run?
What I mean to say is, how can we see or quantify how well FinQuant is performing against no optimisation / a random-search optimisation? Currently, I'm not sure if there's such a way to evaluate how "well" the program is working, if you understand me correctly.
Thanks and I've been having a blast learning from FinQuant!
Example: Monte Carlo optimization of portfolio
Add written output of optimisation functions to README/Documentation-Motivation
Running the example without edit fails.
(.venv) vagrant@linux:~/dev/FinQuant/example$ python3 Example-Build-Portfolio-from-web.py
/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py:260: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
Traceback (most recent call last):
File "Example-Build-Portfolio-from-web.py", line 85, in <module>
pf = build_portfolio(
File "/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py", line 1170, in build_portfolio
File "/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py", line 939, in _build_portfolio_from_api
File "/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py", line 1051, in _build_portfolio_from_df
File "/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py", line 267, in add_stock
File "/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py", line 282, in _update
File "/home/vagrant/dev/FinQuant/.venv/lib/python3.8/site-packages/FinQuant-0.2.2-py3.8.egg/finquant/portfolio.py", line 202, in totalinvestment
ValueError: Total investment must be a float or integer.
Matplotlib Finance offers functions to create financial plots from pandas series/dataframes.
Do research on https://github.com/matplotlib/mplfinance and see how it can be used in FinQuant
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.