{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Rebalancing a Custom Basket\n", "\n", "Here we will go through how to modify your basket's current composition. You may concurrently modify basket details, pricing options, and publishing preferences." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 1: Authenticate & Initialize your session\n", "\n", "First you will import the necessary modules and add your client id and client secret." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from gs_quant.markets.position_set import PositionSet\n", "from gs_quant.markets.baskets import Basket\n", "from gs_quant.session import Environment, GsSession\n", "\n", "client = 'CLIENT ID'\n", "secret = 'CLIENT SECRET'\n", "\n", "GsSession.use(Environment.PROD, client_id=client, client_secret=secret, scopes=('read_product_data read_user_profile',))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2: Fetch your basket and set your changes\n", "\n", "Next you will fetch the basket you'd like to update by passing in any of its identifiers such as BloombergId, Cusip, Ticker, etc. If this is a basket you or someone from your organization created, please make sure your application has admin entitlements or you will not be able to submit the rebalance request. You will then be ready to change any of the properties listed below.\n", "\n", "| Parameter Name | Required? | Description |\n", "|:-------------------|:-----------|:------------|\n", "|position_set |**Required**|Information of constituents associated with the basket. You may provide the weight or quantity for each position. If neither is provided we will distribute the total weight evenly among each position. Please note that any fractional shares will be rounded up to whole numbers.|\n", "|divisor |Optional |Divisor to be applied to the overall position set. Ideally, you should not to change this as it will cause a price deviation on the basket.|\n", "|initial_price |Optional |Price you'd like to reset the basket to. Ideally, you should not to do this as it will cause a price deviation on the basket.|\n", "|publish_to_bloomberg|Optional |If you'd like us to publish your basket to Bloomberg|\n", "|publish_to_reuters |Optional |If you'd like us to publish your basket to Reuters |\n", "|publish_to_factset |Optional |If you'd like us to publish your basket to Factset |\n", "|include_price_history|Optional |Republish price history based on current composition when publishing to Bloomberg|\n", "|reweight |Optional |If you'd like us to reweight positions if input weights don't add up to 1 upon submission|\n", "|weighting_strategy |Optional |Strategy used to price the position set (will be inferred if not indicated). One of Equal, Market Capitalization, Quantity, Weight|\n", "|allow_ca_restricted_assets|Optional|Allow your basket to have constituents that will not be corporate action adjusted in the future (You will recieve a message indicating if this action is needed when attempting to rebalance your basket)|\n", "|allow_limited_access_assets|Optional|Allow basket to have constituents that GS has limited access to (You will recieve a message indicating if this action is needed when attempting to rebalance your basket)|" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "basket = Basket.get('GSMBXXXX')\n", "\n", "basket.publish_to_bloomberg = True\n", "\n", "positions_df = pd.read_excel('path/to/excel.xlsx') # example composition upload from a local excel file\n", "positions_df.columns = ['identifier', 'weight'] # replace weight column with 'quantity' if using number of shares\n", "position_set = PositionSet.from_frame(positions_df)\n", "position_set.resolve()\n", "\n", "position_set.get_positions() # returns a dataframe with each position's identifier, name, Marquee unique identifier, and weight/quantity\n", "\n", "my_basket.position_set = position_set" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3: Submit your changes\n", "\n", "Once you've ensured that your basket composition has been adjusted to your satisfaction, you're ready to officially submit these changes to Marquee! Once you call update on the basket, this request will be sent for approval. You can check on the approval status by calling get_rebalance_approval_status(). The rebalance will begin processing once the request is approved, where you can then poll its status to make sure that it has processed successfully. This will check the report status every 30 seconds for 10 minutes by default, but you can override this option if you prefer as shown below." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "basket.update() # submits the rebalance request to Marquee\n", "\n", "basket.get_rebalance_approval_status() # check approval status of most recent rebalance submission\n", "\n", "basket.poll_status(timeout=120, step=20) # optional: constantly checks rebalance status after request is approved until report succeeds, fails, or the poll times out (this example checks every 20 seconds for 2 minutes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Not happy with the new composition you submitted?\n", "\n", "If your most recent rebalance request is not yet approved, you may either update your composition and submit a new rebalance request using the steps listed above, or you can simply cancel the request." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "basket.cancel_rebalance()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 4 }