예제 #1
0
def test_maximum_sharpe_ratio():
    d = d_pass[3]
    pf = build_portfolio(**d)
    max_sharpe_weights = np.array(
        [0.0, 0.41322217986076903, 0.5867778201392311, 2.2858514942065993e-17])
    ef_opt_weights = pf.ef_maximum_sharpe_ratio()
    assert np.allclose(ef_opt_weights.values.transpose(),
                       max_sharpe_weights,
                       atol=weak_abse)
예제 #2
0
def test_efficient_volatility():
    d = d_pass[3]
    pf = build_portfolio(**d)
    efficient_volatility_weights = np.array(
        [0.0, 0.5325563159992046, 0.4674436840007955, 0.0])
    ef_opt_weights = pf.ef_efficient_volatility(0.191)
    assert np.allclose(ef_opt_weights.values.transpose(),
                       efficient_volatility_weights,
                       atol=weak_abse)
예제 #3
0
 def __init__(self, y_stocks: list, a_float: float, legend_place: str):
     yahoo_list: list = list()
     self._size = a_float
     self._a_title = 'a title'
     self._legend_place = legend_place
     t_s: TimeSpan = y_stocks[0].TimeSpan
     for y_stock in y_stocks:
         yahoo_list.append(y_stock.Ticker)
     pf = build_portfolio(names=yahoo_list,
                          start_date=t_s.StartDateStr,
                          end_date=t_s.EndDateStr,
                          data_api='yfinance')
     self._data = pf.data
     # print(pf.properties())
     print(pf.portfolio.name)
     self._portfolio_df = pf.portfolio
     # annualised expected return
     self._annualised_expected_return = pf.expected_return
     # annualised mean returns
     self._annualised_mean_return_series = pf.comp_mean_returns()
     # volatility
     self._volatility = pf.volatility
     # Sharpe ratio (computed with a risk free rate of 0.005 by default)
     self._sharpe_risk_free005 = pf.sharpe
     # Getting Skewness and Kurtosis of the stocks
     self._skewness_series = pf.skew
     self._kurtosis_series = pf.kurtosis
     # daily returns (percentage change) price_{t} - price_{t=0}) / price_{t=0}
     self._cumulative_return_df = pf.comp_cumulative_returns()
     self._cumulative_log_return_df = pf.comp_daily_log_returns().cumsum()
     # daily percentage changes of returns
     self._pct_chng_return_df = pf.comp_daily_returns()
     self._pct_chng_log_return_df = pf.comp_daily_log_returns()
     # building a portfolio by providing stock data
     # pf = build_portfolio(data=df_data)
     # # Portfolio optimisation
     # ## Efficient Frontier
     # Based on the **Efficient Frontier**, the portfolio can be optimised for
     #  - minimum volatility
     #  - maximum Sharpe ratio
     #  - minimum volatility for a given target return
     #  - maximum Sharpe ratio for a given target volatility
     # See below for an example for each optimisation.
     # if needed, change risk free rate and frequency/time window of the portfolio
     self._freq = pf.freq
     self._risk_free_rate = pf.risk_free_rate
     print('ef_minimum_volatility')
     pf.ef_minimum_volatility(verbose=True)
     # optimisation for maximum Sharpe ratio
     print('ef_maximum_sharpe_ratio')
     pf.ef_maximum_sharpe_ratio(verbose=True)
     # minimum volatility for a given target return of 0.26
     print('ef_efficient_return: target return 0.26')
     pf.ef_efficient_return(0.26, verbose=True)
     # maximum Sharpe ratio for a given target volatility of 0.22
     print('ef_efficient_volatility: target volatility 0.22')
     pf.ef_efficient_volatility(0.22, verbose=True)
예제 #4
0
def test_Stock():
    d = d_pass[3]
    pf = build_portfolio(**d)
    # loop over all stocks stored within pf and check that values
    # are equal to the ones in pf
    for i in range(len(pf.stocks)):
        assert isinstance(pf.get_stock(names[0]), Stock)
        stock = pf.get_stock(names[i])
        assert stock.name == pf.portfolio["Name"][i]
        assert all(stock.data - pf.data[stock.name].to_frame() <= strong_abse)
        assert all(stock.investmentinfo == pf.portfolio.loc[
            pf.portfolio["Name"] == stock.name])
예제 #5
0
def test_get_ef():
    d = d_pass[3]
    pf = build_portfolio(**d)
    ef = pf._get_ef()
    assert isinstance(ef, EfficientFrontier)
    assert isinstance(pf.ef, EfficientFrontier)
    assert pf.ef == ef
    assert (pf.comp_mean_returns(freq=1) == ef.mean_returns).all()
    assert (pf.comp_cov() == ef.cov_matrix).all().all()
    assert pf.freq == ef.freq
    assert pf.risk_free_rate == ef.risk_free_rate
    assert ef.names == pf.portfolio["Name"].values.tolist()
    assert ef.num_stocks == len(pf.stocks)
예제 #6
0
def test_ef_minimum_volatility():
    d = d_pass[3]
    pf = build_portfolio(**d)
    min_vol_weights = np.array([
        0.15515521225480033,
        2.168404344971009e-18,
        0.4946241856546514,
        0.35022060209054834,
    ])
    ef_opt_weights = pf.ef_minimum_volatility()
    assert np.allclose(ef_opt_weights.values.transpose(),
                       min_vol_weights,
                       atol=weak_abse)
예제 #7
0
def test_buildPF_pass_5():
    d = d_pass[5]
    pf = build_portfolio(**d)
    assert isinstance(pf, Portfolio)
    assert isinstance(pf.get_stock(names[0]), Stock)
    assert isinstance(pf.data, pd.DataFrame)
    assert isinstance(pf.portfolio, pd.DataFrame)
    assert len(pf.stocks) == len(pf.data.columns)
    assert pf.data.columns.tolist() == names
    assert pf.data.index.name == "Date"
    assert ((pf.portfolio == df_pf2).all()).all()
    assert (pf.comp_weights() - weights_no_df_pf <= strong_abse).all()
    pf.properties()
예제 #8
0
def test_efficient_return():
    d = d_pass[3]
    pf = build_portfolio(**d)
    efficient_return_weights = np.array([
        0.09339785373366818,
        0.1610699937778475,
        0.5623652130240258,
        0.18316693946445858,
    ])
    ef_opt_weights = pf.ef_efficient_return(0.2542)
    assert np.allclose(ef_opt_weights.values.transpose(),
                       efficient_return_weights,
                       atol=weak_abse)
예제 #9
0
def test_mc_optimisation():
    d = d_pass[3]
    pf = build_portfolio(**d)
    # since the monte carlo optimisation is based on random numbers,
    # we set a seed, so that the results can be compared.
    np.random.seed(seed=0)
    # orig values:
    minvol_res_orig = [
        0.18560926749041448, 0.1333176229402258, 1.3547291311321408
    ]
    maxsharpe_res_orig = [
        0.33033770744503416, 0.16741461860370618, 1.9433052511092475
    ]
    minvol_w_orig = [
        0.09024151309669741,
        0.015766238378839476,
        0.514540537132381,
        0.37945171139208195,
    ]
    maxsharpe_w_orig = [
        0.018038812127367274,
        0.37348740385059126,
        0.5759648343129179,
        0.03250894970912355,
    ]
    labels_orig = ["min Volatility", "max Sharpe Ratio", "Initial Portfolio"]
    xlabel_orig = "Volatility [period=252]"
    ylabel_orig = "Expected Return [period=252]"
    # run Monte Carlo optimisation through pf
    opt_w, opt_res = pf.mc_optimisation(num_trials=500)
    # tests
    assert (minvol_res_orig - opt_res.iloc[0].values <= strong_abse).all()
    assert (maxsharpe_res_orig - opt_res.iloc[1].values <= strong_abse).all()
    assert (minvol_w_orig - opt_w.iloc[0].values <= strong_abse).all()
    assert (maxsharpe_w_orig - opt_w.iloc[1].values <= strong_abse).all()
    # also test the plot
    plt.figure()
    pf.mc_plot_results()
    # get axis object
    ax = plt.gca()
    # only checking legend and axis labels, and assume that the plot
    # was successfully created
    labels_plot = ax.get_legend_handles_labels()[1]
    xlabel_plot = ax.get_xlabel()
    ylabel_plot = ax.get_ylabel()
    assert labels_orig == labels_plot
    assert xlabel_orig == xlabel_plot
    assert ylabel_orig == ylabel_plot
예제 #10
0
def test_buildPF_pass_6():
    d = d_pass[6]
    pf = build_portfolio(**d)
    assert isinstance(pf, Portfolio)
    assert isinstance(pf.data, pd.DataFrame)
    assert isinstance(pf.portfolio, pd.DataFrame)
    assert len(pf.stocks) == len(pf.data.columns)
    assert pf.data.columns.tolist() == names
    assert pf.data.index.name == "Date"
    assert ((pf.portfolio == df_pf).all()).all()
    assert (pf.comp_weights() - weights_df_pf <= strong_abse).all()
    assert expret_orig - pf.expected_return <= strong_abse
    assert vol_orig - pf.volatility <= strong_abse
    assert sharpe_orig - pf.sharpe <= strong_abse
    assert freq_orig - pf.freq <= strong_abse
    assert risk_free_rate_orig - pf.risk_free_rate <= strong_abse
    pf.properties()
예제 #11
0
def test_efficient_frontier():
    d = d_pass[3]
    pf = build_portfolio(**d)
    efrontier = np.array([
        [0.13309804281267365, 0.2],
        [0.13382500317474913, 0.21],
        [0.13491049715255884, 0.22],
        [0.13634357140158387, 0.23],
        [0.13811756026939967, 0.24],
        [0.14021770106367654, 0.25],
        [0.1426296319926618, 0.26],
        [0.1453376889002686, 0.27],
        [0.14832574432346657, 0.28],
        [0.15157724434785497, 0.29],
        [0.15507572162309227, 0.3],
    ])
    targets = [round(0.2 + 0.01 * i, 2) for i in range(11)]
    ef_efrontier = pf.ef_efficient_frontier(targets)
    assert np.allclose(ef_efrontier, efrontier, atol=weak_abse)
예제 #12
0
def test_plot_optimal_portfolios():
    d = d_pass[3]
    pf = build_portfolio(**d)
    # just checking if a plot is successfully created,
    # not checking for content
    pf.ef_plot_optimal_portfolios()
예제 #13
0
In [119]: pf.data                                                                                                                                                            
Out[119]: 
                       GOOG         AMZN         MCD         DIS
                       Date                                                        
                       1962-01-02          NaN          NaN         NaN    0.058360
                       1962-01-03          NaN          NaN         NaN    0.059143
                       1962-01-04          NaN          NaN         NaN    0.059143
                       1962-01-05          NaN          NaN         NaN    0.059339
                       1962-01-08          NaN          NaN         NaN    0.059143
                       ...                 ...          ...         ...         ...
                       2020-12-18  1731.010010  3201.649902  215.080002  172.889999
'''

df_p = pd.DataFrame()
stock_list = [
    "000725", "600837", "600036", "600519", "600276", "601318", "000333",
    "600030", "000858", "002475"
]
#stock_index = '601398'
start_date = '2020-01-01'
end_date = '2020-12-20'
for s1 in stock_list:
    df1 = stock_data(s1, start_date, end_date)
    df_p[s1] = df1.close.values
dates = df1.dt.values
df_p.index = dates
df_p.index.name = 'Date'

pf1 = build_portfolio(data=df_p)
# <codecell>

# here we set the list of names based on the names in
# the DataFrame pf_allocation
names = pf_allocation['Name'].values.tolist()

# dates can be set as datetime or string, as shown below:
start_date = datetime.datetime(2015,1,1)
end_date = '2017-12-31'

# While quandl will download lots of different prices for each stock,
# e.g. high, low, close, etc, FinQuant will extract the column "Adj. Close".

pf = build_portfolio(
    names=names,
    pf_allocation=pf_allocation,
    start_date=start_date,
    end_date=end_date
)

# <markdowncell>

# ## Portfolio is successfully built
# Getting data from the portfolio

# <codecell>

# the portfolio information DataFrame
pf.portfolio

# <codecell>
    new_name = input("Please add stock ticker, or enter 'exit': ")

    # Add the new name to our list
    if new_name != 'exit':
        names.append(new_name)

year = int(input('Enter a year for start date: '))   #year for start date
month = int(input('Enter a month for start date: ')) #month for start date
day = int(input('Enter a day for start date: '))     #day for start date

# use datetime for start_date and end_date
start_date = datetime.datetime(year, month, day)
end_date = datetime.datetime.now()

# Use build_protfolio from finquant with yahoo finance as data api otherwise it will use quandl
pf = build_portfolio(names=names,start_date=start_date, end_date=end_date, data_api="yfinance")

pf.comp_cumulative_returns().plot().axhline(y = 0, color = "black", lw = 3)
plt.title('Cumlative Returns')
plt.show()

# get stock data
x = input("If you want to do moving average for particular data then say 'y' :" )
    
if x in ['y', 'Y', 'yes', 'Yes', 'YES']:
    dis = pf.get_stock(input('Get Stock data for moving average: ')).data.copy(deep=True)
    spans = [10, 50, 100, 150, 200]
    ma = compute_ma(dis, ema, spans, plot=True)
    plt.show()
else:
    print('OK, we will continue to further calculations.....')
예제 #16
0
def test_buildPF_fail_26():
    d = d_fail[26]
    with pytest.raises(Exception):
        build_portfolio(**d)
예제 #17
0
def test_plot_stocks():
    d = d_pass[3]
    pf = build_portfolio(**d)
    # just checking if a plot is successfully created, not checking for content
    pf.plot_stocks()
예제 #18
0
for i,element in enumerate(stock_index_list): 
    try:
        a2 = element
        jj_name_in = jj_name[i]
        list1 = element
        list2 = "\""+list1.replace(",",",\"").replace(",\"","\",\"")+"\""
        sql3 = """
            select dt,lpad(stock_index_raw,6,'0') as stock_index,close
            from stock_dev.baostock_byyear
            where lpad(stock_index_raw,6,'0') in (%s)
        """%(list2)
        df_r1 = spark.sql(sql3)
        df_r2 = df_r1.toPandas()
        df_r2["close"] = [ np.float(x) for x in df_r2["close"].values.tolist()]
        df_r3 = pd.pivot_table(df_r2,index="dt",columns="stock_index",values="close")
        df_r4 = df_r3.dropna()
        df_r4.index.name = 'Date'
        #df_r4["portfolio_return"] = df_r4.sum(axis=1)
        df_r4.columns = df_r4.columns.values.tolist()
        pf = build_portfolio(data=df_r4)
        df_out = pd.DataFrame(port_val(pf))
        df_out["jijin_name"] = jj_name_in
        out_data.append(df_out)
    except:
        pass
df_f1 = pd.concat(out_data)
df_f1.to_csv("tt.csv",index=0)
#print(df_f1.reset_index())

예제 #19
0
# `build_portfolio()` is an interface that can be used in different ways. Two of which is shown below. For more information the docstring is shown below as well.
# In this example `build_portfolio()` is being passed `df_data`, which was read in from file above.

# <codecell>

print(build_portfolio.__doc__)

# <markdowncell>

# ## Building a portfolio with data only
# Below is an example of only passing a `DataFrame` containing data (e.g. stock prices) to `build_portfolio()` in order to build an instance of `Portfolio`. In this case, the allocation of stocks is automatically generated by equally distributing the weights across all stocks.

# <codecell>

# building a portfolio by providing stock data
pf = build_portfolio(data=df_data)

# <markdowncell>

# ### Portfolio is successfully built
# Below it is shown how the allocation of the stocks and the data (e.g. prices) of the stocks can be obtained from the object `pf`.

# <codecell>

# the portfolio information DataFrame
print(pf.portfolio.name)
print(pf.portfolio)

# <codecell>

# the portfolio stock data, prices DataFrame