File size: 2,729 Bytes
33e55ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import yfinance as yf

from scipy.optimize import minimize

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def get_historical_returns(tickers, start_date, end_date):
    """
    Fetch historical returns data for the given tickers.

    Args:
    - tickers: list of strings, tickers of assets
    - start_date: string, start date in the format 'YYYY-MM-DD'
    - end_date: string, end date in the format 'YYYY-MM-DD'

    Returns:
    - pandas DataFrame, historical returns data
    """
    data = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
    returns = data.pct_change().dropna()
    return returns

def get_risk_free_rate_india():
    """
    Get the risk-free rate for the Indian market using the yield of the 10-year Indian Government Bond.

    Returns:
    - float, risk-free rate
    """
    # Ticker symbol for the 10-year Indian Government Bond yield
    bond_ticker = 'INR=X'  # You can replace this with the actual ticker symbol for the bond

    # Fetch the bond data
    bond_data = yf.Ticker(bond_ticker)

    # Get the latest yield
    risk_free_rate_india = bond_data.history(period='1d')['Close'][-1] / 100
    return risk_free_rate_india

def sharpe_ratio(weights, returns, risk_free_rate):
    """
    Calculate the Sharpe Ratio of a portfolio.

    Args:
    - weights: array-like, weights of assets in the portfolio
    - returns: pandas DataFrame, historical returns of assets
    - risk_free_rate: float, risk-free rate of return

    Returns:
    - float, Sharpe Ratio of the portfolio
    """
    portfolio_return = np.sum(weights * returns.mean() * 252)  # 252 trading days in a year
    portfolio_std_dev = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
    sharpe_ratio = (portfolio_return - risk_free_rate) / portfolio_std_dev
    return -sharpe_ratio  # Minimize negative Sharpe Ratio for maximization



def optimize_portfolio(returns, risk_free_rate):
    """
    Optimize portfolio to maximize the Sharpe Ratio.

    Args:
    - returns: pandas DataFrame, historical returns of assets
    - risk_free_rate: float, risk-free rate of return

    Returns:
    - array, optimal weights of assets in the portfolio
    """
    num_assets = len(returns.columns)
    initial_weights = np.array([1 / num_assets] * num_assets)
    bounds = [(0, 1)] * num_assets  # Bounds for asset weights (0 <= weight <= 1)
    constraints = ({'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1})  # Sum of weights equals 1 constraint

    optimized_result = minimize(sharpe_ratio, initial_weights, args=(returns, risk_free_rate),
                                method='SLSQP', bounds=bounds, constraints=constraints)

    return optimized_result.x