{"id":5639,"date":"2025-05-24T18:15:24","date_gmt":"2025-05-24T10:15:24","guid":{"rendered":"http:\/\/cnliutz.pgrm.cc\/?p=5639"},"modified":"2025-05-24T21:17:08","modified_gmt":"2025-05-24T13:17:08","slug":"a%e8%82%a1%e8%87%aa%e6%ae%8b%e9%85%8d%e7%bd%ae%e4%bc%98%e5%8c%96%e5%9d%87%e6%95%b0-%e6%96%b9%e5%b7%ae%e6%a8%a1%e5%9e%8b%e5%ba%94%e7%94%a8%e5%ae%9e%e6%88%98","status":"publish","type":"post","link":"http:\/\/g1n29wqq.ipyingshe.net:5347\/?p=5639","title":{"rendered":"A\u80a1\u914d\u7f6e\u4f18\u5316:\u5747\u6570-\u65b9\u5dee\u6a21\u578b\u5e94\u7528\u5b9e\u6218"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>import akshare as ak\nimport pandas as pd\nimport numpy as np\nfrom scipy.optimize import minimize\n\n# \u5b9a\u4e49\u83b7\u53d6\u80a1\u7968\u6570\u636e\u7684\u51fd\u6570\ndef get_stock_data(codes, start_date, end_date):\n    \"\"\"\n    Fetch historical closing price data for multiple A - share stocks.\n\n    Args:\n        codes (list): A list containing stock codes, each code is a 6 - digit string.\n        start_date (str): The start date of the data in 'YYYYMMDD' format.\n        end_date (str): The end date of the data in 'YYYYMMDD' format.\n\n    Returns:\n        pandas.DataFrame: A DataFrame where each column represents the closing price of a stock,\n                          and the index is the trading date.\n    \"\"\"\n    # Initialize an empty dictionary to store closing price data for each stock\n    data_dict = {}\n    # Iterate through each stock code in the list\n    for code in codes:\n        try:\n            # Use the akshare library to get daily historical data for the current stock\n            df = ak.stock_zh_a_hist(symbol=code, period=\"daily\", start_date=start_date, end_date=end_date)\n            # Check if the DataFrame is empty, indicating no data was retrieved\n            if df.empty:\n                # Print a warning message if no data is found\n                print(f\"Warning: No data found for stock code {code}\")\n                # Skip to the next stock code\n                continue\n            # Convert the '\u65e5\u671f' (date) column to pandas datetime format\n            df&#91;'\u65e5\u671f'] = pd.to_datetime(df&#91;'\u65e5\u671f'])\n            # Set the '\u65e5\u671f' (date) column as the index of the DataFrame\n            df.set_index('\u65e5\u671f', inplace=True)\n            # Add the closing price data of the current stock to the dictionary\n            data_dict&#91;code] = df&#91;'\u6536\u76d8']\n        except Exception as e:\n            # Print an error message if an exception occurs during data retrieval\n            print(f\"Error fetching data for stock code {code}: {e}\")\n    # Convert the dictionary to a DataFrame and return it\n    return pd.DataFrame(data_dict)\n\n# \u5b9a\u4e49\u8ba1\u7b97\u5747\u503c\u3001\u534f\u65b9\u5dee\u77e9\u9635\u548c\u5e74\u5316\u6536\u76ca\u7387\u7684\u51fd\u6570\ndef calculate_statistics(returns):\n    \"\"\"\n    Calculate the annualized mean returns and the annualized covariance matrix of the given returns.\n\n    Args:\n        returns (pandas.DataFrame): A DataFrame containing the daily returns of multiple assets.\n\n    Returns:\n        tuple: A tuple containing two elements:\n            - mean_returns (pandas.Series): A Series containing the annualized mean returns of each asset.\n            - cov_matrix (pandas.DataFrame): A DataFrame representing the annualized covariance matrix of the assets.\n    \"\"\"\n    # Calculate the annualized mean returns by multiplying the daily mean returns by 252,\n    # assuming there are 252 trading days in a year.\n    mean_returns = returns.mean() * 252  # \u5e74\u5316\u5e73\u5747\u6536\u76ca\u7387\n    # Calculate the annualized covariance matrix by multiplying the daily covariance matrix by 252,\n    # assuming there are 252 trading days in a year.\n    cov_matrix = returns.cov() * 252  # \u5e74\u5316\u534f\u65b9\u5dee\u77e9\u9635\n    return mean_returns, cov_matrix\n\n# \u5b9a\u4e49\u8ba1\u7b97\u7ec4\u5408\u6536\u76ca\u7387\u548c\u98ce\u9669\u7684\u51fd\u6570\ndef portfolio_performance(weights, mean_returns, cov_matrix):\n    returns = np.sum(mean_returns * weights)\n    std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))\n    return returns, std\n\n# \u5b9a\u4e49\u6700\u5c0f\u5316\u98ce\u9669\u7684\u76ee\u6807\u51fd\u6570\ndef minimize_risk(weights, mean_returns, cov_matrix):\n    return portfolio_performance(weights, mean_returns, cov_matrix)&#91;1]\n\n# \u5b9a\u4e49\u4f18\u5316\u51fd\u6570\ndef optimize_portfolio(mean_returns, cov_matrix, num_assets):\n    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})  # \u6743\u91cd\u4e4b\u548c\u4e3a 1\n    bounds = tuple((0, 1) for asset in range(num_assets))  # \u6743\u91cd\u8303\u56f4\u5728 0 \u5230 1 \u4e4b\u95f4\n    initial_guess = np.array(num_assets * &#91;1. \/ num_assets])\n    result = minimize(minimize_risk, initial_guess, args=(mean_returns, cov_matrix),\n                      method='SLSQP', bounds=bounds, constraints=constraints)\n    return result\n\n# \u4e3b\u51fd\u6570\ndef main():\n    # \u9009\u62e9\u8981\u5206\u6790\u7684\u80a1\u7968\u4ee3\u7801\uff0c\u53bb\u6389 sh \u548c sz \u524d\u7f00\n    stock_codes = &#91;'600519', '000858', '601318', '002594']\n    start_date = '20240101'\n    end_date = '20240523'\n\n    # \u83b7\u53d6\u80a1\u7968\u6570\u636e\n    stock_data = get_stock_data(stock_codes, start_date, end_date)\n\n    if stock_data.empty:\n        print(\"No valid stock data obtained. Exiting...\")\n        return\n\n    # \u8ba1\u7b97\u65e5\u6536\u76ca\u7387\uff0c\u6ce8\u610f\u6bcf\u65e5\u6da8\u8dcc\u7387\u548c\u65e5\u6536\u76ca\u7387\u7684\u533a\u522b\uff01\n    # \u65e5\u6536\u76ca\u7387 = (\u5f53\u65e5\u6536\u76d8\u4ef7 - \u524d\u4e00\u65e5\u6536\u76d8\u4ef7) \/ \u524d\u4e00\u65e5\u6536\u76d8\u4ef7 \n    # \u6da8\u8dcc\u7387 = \u5f53\u65e5\u6536\u76d8\u4ef7 \/ \u524d\u4e00\u65e5\u6536\u76d8\u4ef7 - 1\n    \n    returns = stock_data.pct_change()\n    # # \u624b\u52a8\u8ba1\u7b97\u65e5\u6536\u76ca\u7387\u5e76\u9a8c\u8bc1\n    # manual_returns = pd.DataFrame(index=returns.index, columns=returns.columns)\n    # for code in stock_codes:\n    #     for i in range(1, len(stock_data)):\n    #         prev_close = stock_data&#91;code].iloc&#91;i - 1]\n    #         current_close = stock_data&#91;code].iloc&#91;i]\n    #         manual_returns&#91;code].iloc&#91;i] = (current_close - prev_close) \/ prev_close\n    # manual_returns = manual_returns.dropna()\n\n    print(\"\u6536\u76d8\u4ef7\u6570\u636e:\")\n    print(stock_data.tail())\n    print(\"\u81ea\u52a8\u8ba1\u7b97\u7684\u65e5\u6536\u76ca\u7387(%):\")\n    print(returns.tail() * 100)\n    # print(\"\u624b\u52a8\u8ba1\u7b97\u7684\u65e5\u6536\u76ca\u7387(%):\")\n    # print(manual_returns.tail() * 100)\n\n    returns = returns.dropna()\n\n    # \u8ba1\u7b97\u5747\u503c\u548c\u534f\u65b9\u5dee\u77e9\u9635\n    mean_returns, cov_matrix = calculate_statistics(returns)\n\n    num_assets = len(stock_codes)\n\n    # \u8fdb\u884c\u6295\u8d44\u7ec4\u5408\u4f18\u5316\n    optimal_result = optimize_portfolio(mean_returns, cov_matrix, num_assets)\n\n    # \u8f93\u51fa\u6700\u4f18\u6743\u91cd\n    optimal_weights = optimal_result.x\n    optimal_returns, optimal_std = portfolio_performance(optimal_weights, mean_returns, cov_matrix)\n\n    print(\"\u6700\u4f18\u6743\u91cd:\")\n    for i in range(num_assets):\n        print(f\"{stock_codes&#91;i]}: {optimal_weights&#91;i]:.4f}\")\n    print(f\"\u6700\u4f18\u7ec4\u5408\u5e74\u5316\u6536\u76ca\u7387: {optimal_returns:.4f}\")\n    print(f\"\u6700\u4f18\u7ec4\u5408\u5e74\u5316\u98ce\u9669\uff08\u6807\u51c6\u5dee\uff09: {optimal_std:.4f}\")\n\nif __name__ == \"__main__\":\n    main()\n<\/code><\/pre>\n\n\n\n<p>\u6536\u76d8\u4ef7\u6570\u636e:<br>                        600519 000858 601318 002594<br>\u65e5\u671f<br>2024-05-17 1715.00 156.41 45.20 219.59<br>2024-05-20 1709.00 157.30 45.46 222.87<br>2024-05-21 1705.00 156.54 45.40 218.78<br>2024-05-22 1697.71 155.12 45.40 216.92<br>2024-05-23 1692.01 153.60 44.78 214.95<br>\u81ea\u52a8\u8ba1\u7b97\u7684\u65e5\u6536\u76ca\u7387(%):<br>                            600519        000858        601318      002594<br>\u65e5\u671f<br>2024-05-17 0.616016 1.531970 4.994193    0.586322<br>2024-05-20 -0.349854 0.569017 0.575221 1.493693<br>2024-05-21 -0.234055 -0.483153 -0.131984 -1.835151<br>2024-05-22 -0.427566 -0.907116 0.000000 -0.850169<br>2024-05-23 -0.335746 -0.979887 -1.365639 -0.908169<br>\u6700\u4f18\u6743\u91cd:<br>600519: 0.7324<br>000858: 0.0000<br>601318: 0.2205<br>002594: 0.0472<br>\u6700\u4f18\u7ec4\u5408\u5e74\u5316\u6536\u76ca\u7387: 0.1205<br>\u6700\u4f18\u7ec4\u5408\u5e74\u5316\u98ce\u9669\uff08\u6807\u51c6\u5dee\uff09: 0.1801<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6536\u76d8\u4ef7\u6570\u636e: 600519 000858 601318 002594\u65e5\u671f2024 <span class=\"readmore\"><a href=\"http:\/\/g1n29wqq.ipyingshe.net:5347\/?p=5639\">Continue Reading<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,24],"tags":[],"class_list":["post-5639","post","type-post","status-publish","format-standard","hentry","category-2","category-24"],"_links":{"self":[{"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=\/wp\/v2\/posts\/5639","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5639"}],"version-history":[{"count":2,"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=\/wp\/v2\/posts\/5639\/revisions"}],"predecessor-version":[{"id":5641,"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=\/wp\/v2\/posts\/5639\/revisions\/5641"}],"wp:attachment":[{"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5639"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5639"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/g1n29wqq.ipyingshe.net:5347\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5639"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}