{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3 (ipykernel)", "language": "python" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Example 4:Portfolio Optimization\n", "Suppose we have a portfolio optimization problem below.\n", "\n", "$$\n", " \\min_{\\omega_1, \\cdots, \\omega_n}{\\sum\\limits^n_{i=1}(\\rho(\\omega_i)+\\frac{1}{2}\\omega_i^2)}, \\qquad \\text{s.t.} \\ \\sum\\limits_{i=1}^n \\omega_i =1, \\ \\text{and} \\ \\sum\\limits_{i=1}^n \\omega_i r_i \\geq \\alpha,\n", "$$\n", "\n", "where $n$ is the number of stocks, $\\omega_i \\in \\mathbb{R}$ is the weight of the $i$-th stock with $\\omega_i < 0$ meaning shorting the stock and $\\omega_i > 0$ longing the stock, $\\gamma_i \\in \\mathbb{R}$ is the expected return of the $i$-th stock, $\\alpha \\in \\mathbb{R}$ is the minimum requirements for the expected return of the portfolio, and $\\rho: \\mathbb{R} \\rightarrow \\mathbb{R}^{+}$ is the transaction cost given by a univariate convex PLQ function. The workflow is similar to the previous example except for the input representation of the prototype PLQ function." ], "metadata": { "id": "1BcN65fJ3VFp" } }, { "cell_type": "code", "source": [ "import numpy as np\n", "z = np.linspace(-1,1,1000)\n", "interval0 = [1 if (-0.25<=i<=0.25) else 0 for i in z]\n", "interval1 = [1 if (-0.5<=i<-0.25 or 0.25=0.75) else 0 for i in z]\n", "f = 0.4* (np.abs(z)) * interval0 + (0.8* (np.abs(z)-0.25)+0.1) * interval1 + (1.2* (np.abs(z)-0.5)+0.3) * interval2 + (1.6* (np.abs(z)-0.75)+0.6) * interval3" ], "metadata": { "id": "L36-fce53lAz", "ExecuteTime": { "end_time": "2025-01-03T09:29:56.525453Z", "start_time": "2025-01-03T09:29:56.468445Z" } }, "outputs": [], "execution_count": 1 }, { "cell_type": "code", "source": [ "import matplotlib.pyplot as plt\n", "\n", "plt.figure(figsize=(4, 3))\n", "plt.plot(z, f, label='Transaction cost')\n", "plt.legend()\n", "plt.xlabel('z')\n", "plt.ylabel('c(z)')\n", "plt.title('Transcation Cost')\n", "plt.show()" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 333 }, "id": "b--cyBZ96RAi", "outputId": "c1030f8e-2b61-47f8-b096-5df734d9807c", "ExecuteTime": { "end_time": "2025-01-03T09:29:57.358941Z", "start_time": "2025-01-03T09:29:57.139150Z" } }, "outputs": [ { "data": { "text/plain": [ "
" ], "image/png": "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" }, "metadata": {}, "output_type": "display_data" } ], "execution_count": 2 }, { "cell_type": "markdown", "source": [ "# 1.Data Generation" ], "metadata": { "id": "CX5j9qU28AB3" } }, { "cell_type": "code", "source": [ "from plqcom import PLQLoss, plq_to_rehloss, affine_transformation\n", "from rehline import ReHLine" ], "metadata": { "id": "BxQroEfQUwzP", "ExecuteTime": { "end_time": "2025-01-03T09:29:58.085091Z", "start_time": "2025-01-03T09:29:57.512088Z" } }, "outputs": [], "execution_count": 3 }, { "cell_type": "code", "source": [ "# Generate a portfolio dataset\n", "n, C = 10, 0.5\n", "np.random.seed(1024)\n", "X = np.eye(n)\n", "r = -0.5 +np.random.rand(10)" ], "metadata": { "id": "NRo0SGwnweGz", "ExecuteTime": { "end_time": "2025-01-03T09:29:58.089535Z", "start_time": "2025-01-03T09:29:58.087740Z" } }, "outputs": [], "execution_count": 4 }, { "cell_type": "code", "source": [ "X" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "E_NCk1AGwrpB", "outputId": "27722243-176e-496d-e82e-b6de308889d3", "ExecuteTime": { "end_time": "2025-01-03T09:29:58.097561Z", "start_time": "2025-01-03T09:29:58.095407Z" } }, "outputs": [ { "data": { "text/plain": [ "array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n", " [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n", " [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n", " [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n", " [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n", " [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n", " [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n", " [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 5 }, { "cell_type": "code", "source": [ "r" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "xm1xoRYXwtT6", "outputId": "43f3791a-8594-4428-d080-e16595bd4025", "ExecuteTime": { "end_time": "2025-01-03T09:29:58.153690Z", "start_time": "2025-01-03T09:29:58.151527Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 0.14769123, 0.49691358, 0.01880326, 0.15811273, 0.09906347,\n", " 0.25306733, -0.36375287, -0.49588288, -0.35049112, 0.198439 ])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 6 }, { "cell_type": "markdown", "source": [ "# 2. Create and Decompose the PLQ Loss" ], "metadata": { "id": "wR78j0ii8Z20" } }, { "cell_type": "markdown", "source": [ "Create the PLQ Loss object with the points." ], "metadata": { "id": "ru0onPXO8fYh" } }, { "cell_type": "code", "source": [ "# Create a PLQLoss object\n", "plqloss = PLQLoss(points=np.array([[-0.75,0.6],[-0.5,0.3],[-0.25,0.1],[0,0],[0.25,0.1],[0.5,0.3],[0.75,0.6]]),\n", " form='points')" ], "metadata": { "id": "vQ871_O-xKnU", "ExecuteTime": { "end_time": "2025-01-03T09:29:59.352617Z", "start_time": "2025-01-03T09:29:59.349465Z" } }, "outputs": [], "execution_count": 7 }, { "cell_type": "markdown", "source": [ "Convert the PLQ Loss to ReHLoss by calling its method plq_to_rehloss()" ], "metadata": { "id": "7qaY9j7r8r0s" } }, { "cell_type": "code", "source": [ "# Decompose the SVM loss into PLQ composite loss\n", "rehloss = plq_to_rehloss(plqloss)" ], "metadata": { "id": "c4RhTr0H8vz0", "ExecuteTime": { "end_time": "2025-01-03T09:29:59.943279Z", "start_time": "2025-01-03T09:29:59.940743Z" } }, "outputs": [], "execution_count": 8 }, { "cell_type": "markdown", "source": [ "# 3.Broadcast to all samples" ], "metadata": { "id": "aUs0g_yc8w9R" } }, { "cell_type": "markdown", "source": [ "For this classication problem,\n", "$L_i(z_i)=L(z)$ hich is a affine transformation of $L(z)$ with $p=1$, $q=0$, $c=0.5$" ], "metadata": { "id": "TJD4gytM852F" } }, { "cell_type": "code", "source": [ "# Broadcast the PLQ composite loss to all samples\n", "rehloss = affine_transformation(rehloss, n=X.shape[0], c=C, p=1, q=0)" ], "metadata": { "id": "2nm4wxpLzjnP", "ExecuteTime": { "end_time": "2025-01-03T09:30:00.835566Z", "start_time": "2025-01-03T09:30:00.833510Z" } }, "outputs": [], "execution_count": 9 }, { "cell_type": "code", "source": [ "print(rehloss.relu_coef.shape)\n", "print(\"First ten sample relu coefficients: %s\" % rehloss.relu_coef[0][:10])\n", "print(\"First ten sample relu intercepts: %s\" % rehloss.relu_intercept[0][:10])" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Sa5OF9UYzpOG", "outputId": "b29a6439-c8e7-4864-f45b-e1429307aa99", "ExecuteTime": { "end_time": "2025-01-03T09:30:01.177404Z", "start_time": "2025-01-03T09:30:01.174810Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(6, 10)\n", "First ten sample relu coefficients: [-0.2 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2]\n", "First ten sample relu intercepts: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n" ] } ], "execution_count": 10 }, { "cell_type": "markdown", "source": [ "# 4. Use ReHLine to solve the problem" ], "metadata": { "id": "H0Etm44s9dPj" } }, { "cell_type": "code", "source": [ "A = np.array([r,np.ones(10)])\n", "b = np.array([-0.3,-1])\n", "clf = ReHLine()\n", "clf.U, clf.V, clf.C, clf.A, clf.b = rehloss.relu_coef, rehloss.relu_intercept, C, A, b\n", "clf.fit(X=X)\n", "print('sol privided by rehline: %s' % clf.coef_)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Kk03dawjzrpH", "outputId": "43f018bd-f2e6-44cb-b569-99bd4600be27", "ExecuteTime": { "end_time": "2025-01-03T09:30:03.056964Z", "start_time": "2025-01-03T09:30:03.053230Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "sol privided by rehline: [ 1.34941891e-01 2.54603696e-01 1.69638746e-02 1.44481245e-01\n", " 9.04303147e-02 2.31398247e-01 2.69356477e-18 -5.41557530e-02\n", " -4.84502846e-19 1.81394027e-01]\n" ] } ], "execution_count": 11 } ] }