485 lines
27 KiB
HTML
485 lines
27 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="description" content="MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\(','\)']]}}); Hello! Glad to meet you. I'm currently a student at Columbia University studying Financial Engineering, and want to give an ...">
|
|
<meta name="keywords" content="introduction, trading">
|
|
<link rel="icon" href="https://bspeice.github.io/favicon.ico">
|
|
|
|
<title>Welcome, and an algorithm - Bradlee Speice</title>
|
|
|
|
<!-- Stylesheets -->
|
|
<link href="https://bspeice.github.io/theme/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://bspeice.github.io/theme/css/fonts.css" rel="stylesheet">
|
|
<link href="https://bspeice.github.io/theme/css/nest.css" rel="stylesheet">
|
|
<link href="https://bspeice.github.io/theme/css/pygment.css" rel="stylesheet">
|
|
<!-- /Stylesheets -->
|
|
|
|
<!-- RSS Feeds -->
|
|
<link href="https://bspeice.github.io/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Bradlee Speice Full Atom Feed" />
|
|
<link href="https://bspeice.github.io/feeds/blog.atom.xml" type="application/atom+xml" rel="alternate" title="Bradlee Speice Categories Atom Feed" />
|
|
<!-- /RSS Feeds -->
|
|
|
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
|
<!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
|
<![endif]-->
|
|
|
|
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- Header -->
|
|
<div class="header-container gradient">
|
|
|
|
<!-- Static navbar -->
|
|
<div class="container">
|
|
<div class="header-nav">
|
|
<div class="header-logo">
|
|
<a class="pull-left" href="https://bspeice.github.io/"><img class="mr20" src="https://bspeice.github.io/images/logo.svg" alt="logo">Bradlee Speice</a>
|
|
</div>
|
|
<div class="nav pull-right">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /Static navbar -->
|
|
|
|
<!-- Header -->
|
|
<!-- Header -->
|
|
<div class="container header-wrapper">
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<div class="header-content">
|
|
<h1 class="header-title">Welcome, and an algorithm</h1>
|
|
<p class="header-date"> <a href="https://bspeice.github.io/author/bradlee-speice.html">Bradlee Speice</a>, Thu 19 November 2015, Sat 05 December 2015, <a href="https://bspeice.github.io/category/blog.html">Blog</a></p>
|
|
<div class="header-underline"></div>
|
|
<div class="clearfix"></div>
|
|
<p class="pull-right header-tags">
|
|
<span class="glyphicon glyphicon-tags mr5" aria-hidden="true"></span>
|
|
<a href="https://bspeice.github.io/tag/introduction.html">introduction</a>, <a href="https://bspeice.github.io/tag/trading.html">trading</a> </p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /Header -->
|
|
<!-- /Header -->
|
|
|
|
</div>
|
|
<!-- /Header -->
|
|
|
|
|
|
<!-- Content -->
|
|
<div class="container content">
|
|
<script type="text/x-mathjax-config">
|
|
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\(','\)']]}});
|
|
</script>
|
|
|
|
<script async src='https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML'></script>
|
|
|
|
<p>Hello! Glad to meet you. I'm currently a student at Columbia University
|
|
studying Financial Engineering, and want to give an overview of the projects
|
|
I'm working on!</p>
|
|
<p>To start things off, Columbia has been hosting a trading competition that
|
|
myself and another partner are competing in. I'm including a notebook of the
|
|
algorithm that we're using, just to give a simple overview of a miniature
|
|
algorithm.</p>
|
|
<p>The competition is scored in 3 areas:</p>
|
|
<ul>
|
|
<li>Total return</li>
|
|
<li><a href="1">Sharpe ratio</a></li>
|
|
<li>Maximum drawdown</li>
|
|
</ul>
|
|
<p>Our algorithm uses a basic momentum strategy: in the given list of potential
|
|
portfolios, pick the stocks that have been performing well in the past 30
|
|
days. Then, optimize for return subject to the drawdown being below a specific
|
|
level. We didn't include the Sharpe ratio as a constraint, mostly because
|
|
we were a bit late entering the competition.</p>
|
|
<p>I'll be updating this post with the results of our algorithm as they come along!</p>
|
|
<hr />
|
|
<p><strong>UPDATE 12/5/2015</strong>: Now that the competition has ended, I wanted to update
|
|
how the algorithm performed. Unfortunately, it didn't do very well. I'm planning
|
|
to make some tweaks over the coming weeks, and do another forward test in January.</p>
|
|
<ul>
|
|
<li>After week 1: Down .1%</li>
|
|
<li>After week 2: Down 1.4%</li>
|
|
<li>After week 3: Flat</li>
|
|
</ul>
|
|
<p>And some statistics for all teams participating in the competition:</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th></th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Max Return</td>
|
|
<td>74.1%</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Min Return</td>
|
|
<td>-97.4%</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Average Return</td>
|
|
<td>-.1%</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Std Dev of Returns</td>
|
|
<td>19.6%</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<hr />
|
|
<p>
|
|
<div class="cell border-box-sizing text_cell rendered">
|
|
<div class="prompt input_prompt">
|
|
</div>
|
|
<div class="inner_cell">
|
|
<div class="text_cell_render border-box-sizing rendered_html">
|
|
<h1 id="Trading-Competition-Optimization">Trading Competition Optimization<a class="anchor-link" href="#Trading-Competition-Optimization">¶</a></h1><h3 id="Goal:-Max-return-given-maximum-Sharpe-and-Drawdown">Goal: Max return given maximum Sharpe and Drawdown<a class="anchor-link" href="#Goal:-Max-return-given-maximum-Sharpe-and-Drawdown">¶</a></h3>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="cell border-box-sizing code_cell rendered">
|
|
<div class="input">
|
|
<div class="prompt input_prompt">In [1]:</div>
|
|
<div class="inner_cell">
|
|
<div class="input_area">
|
|
<div class=" highlight hl-ipython3"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="k">import</span> <span class="n">display</span>
|
|
<span class="kn">import</span> <span class="nn">Quandl</span>
|
|
<span class="kn">from</span> <span class="nn">datetime</span> <span class="k">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span>
|
|
|
|
<span class="n">tickers</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'XOM'</span><span class="p">,</span> <span class="s1">'CVX'</span><span class="p">,</span> <span class="s1">'CLB'</span><span class="p">,</span> <span class="s1">'OXY'</span><span class="p">,</span> <span class="s1">'SLB'</span><span class="p">]</span>
|
|
<span class="n">market_ticker</span> <span class="o">=</span> <span class="s1">'GOOG/NYSE_VOO'</span>
|
|
<span class="n">lookback</span> <span class="o">=</span> <span class="mi">30</span>
|
|
<span class="n">d_col</span> <span class="o">=</span> <span class="s1">'Close'</span>
|
|
|
|
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="n">tick</span><span class="p">:</span> <span class="n">Quandl</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'YAHOO/{}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">tick</span><span class="p">))[</span><span class="o">-</span><span class="n">lookback</span><span class="p">:]</span> <span class="k">for</span> <span class="n">tick</span> <span class="ow">in</span> <span class="n">tickers</span><span class="p">}</span>
|
|
<span class="n">market</span> <span class="o">=</span> <span class="n">Quandl</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">market_ticker</span><span class="p">)</span>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="cell border-box-sizing text_cell rendered">
|
|
<div class="prompt input_prompt">
|
|
</div>
|
|
<div class="inner_cell">
|
|
<div class="text_cell_render border-box-sizing rendered_html">
|
|
<h1 id="Calculating-the-Return">Calculating the Return<a class="anchor-link" href="#Calculating-the-Return">¶</a></h1><p>We first want to know how much each ticker returned over the prior period.</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="cell border-box-sizing code_cell rendered">
|
|
<div class="input">
|
|
<div class="prompt input_prompt">In [2]:</div>
|
|
<div class="inner_cell">
|
|
<div class="input_area">
|
|
<div class=" highlight hl-ipython3"><pre><span class="n">returns</span> <span class="o">=</span> <span class="p">{</span><span class="n">tick</span><span class="p">:</span> <span class="n">data</span><span class="p">[</span><span class="n">tick</span><span class="p">][</span><span class="n">d_col</span><span class="p">]</span><span class="o">.</span><span class="n">pct_change</span><span class="p">()</span> <span class="k">for</span> <span class="n">tick</span> <span class="ow">in</span> <span class="n">tickers</span><span class="p">}</span>
|
|
|
|
<span class="n">display</span><span class="p">({</span><span class="n">tick</span><span class="p">:</span> <span class="n">returns</span><span class="p">[</span><span class="n">tick</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">()</span> <span class="k">for</span> <span class="n">tick</span> <span class="ow">in</span> <span class="n">tickers</span><span class="p">})</span>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="output_wrapper">
|
|
<div class="output">
|
|
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>{'CLB': -0.0016320202164526894,
|
|
'CVX': 0.0010319531629488911,
|
|
'OXY': 0.00093418904454400551,
|
|
'SLB': 0.00098431254720448159,
|
|
'XOM': 0.00044165797556096868}</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="cell border-box-sizing text_cell rendered">
|
|
<div class="prompt input_prompt">
|
|
</div>
|
|
<div class="inner_cell">
|
|
<div class="text_cell_render border-box-sizing rendered_html">
|
|
<h1 id="Calculating-the-Sharpe-ratio">Calculating the Sharpe ratio<a class="anchor-link" href="#Calculating-the-Sharpe-ratio">¶</a></h1><p>Sharpe: ${R - R_M \over \sigma}$</p>
|
|
<p>We use the average return over the lookback period, minus the market average return, over the ticker standard deviation to calculate the Sharpe. Shorting a stock turns a negative Sharpe positive.</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="cell border-box-sizing code_cell rendered">
|
|
<div class="input">
|
|
<div class="prompt input_prompt">In [3]:</div>
|
|
<div class="inner_cell">
|
|
<div class="input_area">
|
|
<div class=" highlight hl-ipython3"><pre><span class="n">market_returns</span> <span class="o">=</span> <span class="n">market</span><span class="o">.</span><span class="n">pct_change</span><span class="p">()</span>
|
|
|
|
<span class="n">sharpe</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">ret</span><span class="p">:</span> <span class="p">(</span><span class="n">ret</span><span class="o">.</span><span class="n">mean</span><span class="p">()</span> <span class="o">-</span> <span class="n">market_returns</span><span class="p">[</span><span class="n">d_col</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">())</span> <span class="o">/</span> <span class="n">ret</span><span class="o">.</span><span class="n">std</span><span class="p">()</span>
|
|
<span class="n">sharpes</span> <span class="o">=</span> <span class="p">{</span><span class="n">tick</span><span class="p">:</span> <span class="n">sharpe</span><span class="p">(</span><span class="n">returns</span><span class="p">[</span><span class="n">tick</span><span class="p">])</span> <span class="k">for</span> <span class="n">tick</span> <span class="ow">in</span> <span class="n">tickers</span><span class="p">}</span>
|
|
|
|
<span class="n">display</span><span class="p">(</span><span class="n">sharpes</span><span class="p">)</span>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="output_wrapper">
|
|
<div class="output">
|
|
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>{'CLB': -0.10578734457846127,
|
|
'CVX': 0.027303529817677398,
|
|
'OXY': 0.022622210057414487,
|
|
'SLB': 0.026950946344858676,
|
|
'XOM': -0.0053519259698605499}</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="cell border-box-sizing text_cell rendered">
|
|
<div class="prompt input_prompt">
|
|
</div>
|
|
<div class="inner_cell">
|
|
<div class="text_cell_render border-box-sizing rendered_html">
|
|
<h1 id="Calculating-the-drawdown">Calculating the drawdown<a class="anchor-link" href="#Calculating-the-drawdown">¶</a></h1><p>This one is easy - what is the maximum daily change over the lookback period? That is, because we will allow short positions, we are not concerned strictly with maximum downturn, but in general, what is the largest 1-day change?</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="cell border-box-sizing code_cell rendered">
|
|
<div class="input">
|
|
<div class="prompt input_prompt">In [4]:</div>
|
|
<div class="inner_cell">
|
|
<div class="input_area">
|
|
<div class=" highlight hl-ipython3"><pre><span class="n">drawdown</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">ret</span><span class="p">:</span> <span class="n">ret</span><span class="o">.</span><span class="n">abs</span><span class="p">()</span><span class="o">.</span><span class="n">max</span><span class="p">()</span>
|
|
<span class="n">drawdowns</span> <span class="o">=</span> <span class="p">{</span><span class="n">tick</span><span class="p">:</span> <span class="n">drawdown</span><span class="p">(</span><span class="n">returns</span><span class="p">[</span><span class="n">tick</span><span class="p">])</span> <span class="k">for</span> <span class="n">tick</span> <span class="ow">in</span> <span class="n">tickers</span><span class="p">}</span>
|
|
|
|
<span class="n">display</span><span class="p">(</span><span class="n">drawdowns</span><span class="p">)</span>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="output_wrapper">
|
|
<div class="output">
|
|
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>{'CLB': 0.043551495607375035,
|
|
'CVX': 0.044894389686214398,
|
|
'OXY': 0.051424517867144637,
|
|
'SLB': 0.034774627850375328,
|
|
'XOM': 0.035851524605672758}</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="cell border-box-sizing text_cell rendered">
|
|
<div class="prompt input_prompt">
|
|
</div>
|
|
<div class="inner_cell">
|
|
<div class="text_cell_render border-box-sizing rendered_html">
|
|
<h1 id="Performing-the-optimization">Performing the optimization<a class="anchor-link" href="#Performing-the-optimization">¶</a></h1><p>$\begin{align}
|
|
max\ \ & \mu \cdot \omega\\
|
|
s.t.\ \ & \vec{1} \omega = 1\\
|
|
& \vec{S} \omega \ge s\\
|
|
& \vec{D} \cdot | \omega | \le d\\
|
|
& \left|\omega\right| \le l\\
|
|
\end{align}$</p>
|
|
<p>We want to maximize average return subject to having a full portfolio, Sharpe above a specific level, drawdown below a level, and leverage not too high - that is, don't have huge long/short positions.</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="cell border-box-sizing code_cell rendered">
|
|
<div class="input">
|
|
<div class="prompt input_prompt">In [5]:</div>
|
|
<div class="inner_cell">
|
|
<div class="input_area">
|
|
<div class=" highlight hl-ipython3"><pre><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
|
|
<span class="kn">from</span> <span class="nn">scipy.optimize</span> <span class="k">import</span> <span class="n">minimize</span>
|
|
|
|
<span class="c1">#sharpe_limit = .1</span>
|
|
<span class="n">drawdown_limit</span> <span class="o">=</span> <span class="o">.</span><span class="mi">05</span>
|
|
<span class="n">leverage</span> <span class="o">=</span> <span class="mi">250</span>
|
|
|
|
<span class="c1"># Use the map so we can guarantee we maintain the correct order</span>
|
|
<span class="c1"># sharpe_a = np.array(list(map(lambda tick: sharpes[tick], tickers))) * -1 # So we can write as upper-bound</span>
|
|
<span class="n">dd_a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">tick</span><span class="p">:</span> <span class="n">drawdowns</span><span class="p">[</span><span class="n">tick</span><span class="p">],</span> <span class="n">tickers</span><span class="p">)))</span>
|
|
<span class="n">returns_a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">tick</span><span class="p">:</span> <span class="n">returns</span><span class="p">[</span><span class="n">tick</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">(),</span> <span class="n">tickers</span><span class="p">)))</span> <span class="c1"># Because minimizing</span>
|
|
|
|
<span class="n">meets_sharpe</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">sharpe_a</span><span class="p">)</span> <span class="o">-</span> <span class="n">sharpe_limit</span>
|
|
<span class="k">def</span> <span class="nf">meets_dd</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
|
<span class="n">portfolio</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="n">portfolio</span> <span class="o"><</span> <span class="o">.</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="c1"># If there are no stocks in the portfolio,</span>
|
|
<span class="c1"># we can accidentally induce division by 0,</span>
|
|
<span class="c1"># or division by something small enough to cause infinity</span>
|
|
<span class="k">return</span> <span class="mi">0</span>
|
|
|
|
<span class="k">return</span> <span class="n">drawdown_limit</span> <span class="o">-</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">dd_a</span><span class="p">)</span> <span class="o">/</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
|
|
|
|
<span class="n">is_portfolio</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">sum</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
|
|
|
|
<span class="k">def</span> <span class="nf">within_leverage</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">leverage</span> <span class="o">-</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
|
|
|
|
<span class="n">objective</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">sum</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">returns_a</span><span class="p">)</span> <span class="o">*</span> <span class="o">-</span><span class="mi">1</span> <span class="c1"># Because we're minimizing</span>
|
|
<span class="n">bounds</span> <span class="o">=</span> <span class="p">((</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">),)</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">tickers</span><span class="p">)</span>
|
|
<span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">tickers</span><span class="p">))</span>
|
|
|
|
<span class="n">constraints</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s1">'type'</span><span class="p">:</span> <span class="s1">'eq'</span><span class="p">,</span>
|
|
<span class="s1">'fun'</span><span class="p">:</span> <span class="n">is_portfolio</span>
|
|
<span class="p">},</span> <span class="p">{</span>
|
|
<span class="s1">'type'</span><span class="p">:</span> <span class="s1">'ineq'</span><span class="p">,</span>
|
|
<span class="s1">'fun'</span><span class="p">:</span> <span class="n">within_leverage</span>
|
|
<span class="c1">#}, {</span>
|
|
<span class="c1"># 'type': 'ineq',</span>
|
|
<span class="c1"># 'fun': meets_sharpe</span>
|
|
<span class="p">},</span> <span class="p">{</span>
|
|
<span class="s1">'type'</span><span class="p">:</span> <span class="s1">'ineq'</span><span class="p">,</span>
|
|
<span class="s1">'fun'</span><span class="p">:</span> <span class="n">meets_dd</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="n">optimal</span> <span class="o">=</span> <span class="n">minimize</span><span class="p">(</span><span class="n">objective</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">bounds</span><span class="o">=</span><span class="n">bounds</span><span class="p">,</span> <span class="n">constraints</span><span class="o">=</span><span class="n">constraints</span><span class="p">,</span>
|
|
<span class="n">options</span><span class="o">=</span><span class="p">{</span><span class="s1">'maxiter'</span><span class="p">:</span> <span class="mi">500</span><span class="p">})</span>
|
|
|
|
<span class="c1"># Optimization time!</span>
|
|
<span class="n">display</span><span class="p">(</span><span class="n">optimal</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
|
|
|
|
<span class="n">display</span><span class="p">(</span><span class="s2">"Holdings: {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span> <span class="n">optimal</span><span class="o">.</span><span class="n">x</span><span class="p">))))</span>
|
|
|
|
<span class="n">expected_return</span> <span class="o">=</span> <span class="n">optimal</span><span class="o">.</span><span class="n">fun</span> <span class="o">*</span> <span class="o">-</span><span class="mi">100</span> <span class="c1"># multiply by -100 to scale, and compensate for minimizing</span>
|
|
<span class="n">display</span><span class="p">(</span><span class="s2">"Expected Return: {:.3f}%"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">expected_return</span><span class="p">))</span>
|
|
|
|
<span class="n">expected_drawdown</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">optimal</span><span class="o">.</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">dd_a</span><span class="p">)</span> <span class="o">/</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">optimal</span><span class="o">.</span><span class="n">x</span><span class="p">))</span> <span class="o">*</span> <span class="mi">100</span>
|
|
<span class="n">display</span><span class="p">(</span><span class="s2">"Expected Max Drawdown: {0:.2f}%"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">expected_drawdown</span><span class="p">))</span>
|
|
|
|
<span class="c1"># TODO: Calculate expected Sharpe</span>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="output_wrapper">
|
|
<div class="output">
|
|
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>'Optimization terminated successfully.'</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>"Holdings: [('XOM', 5.8337945679814904), ('CVX', 42.935064321851307), ('CLB', -124.5), ('OXY', 36.790387773552119), ('SLB', 39.940753336615096)]"</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>'Expected Return: 32.375%'</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="output_area"><div class="prompt"></div>
|
|
|
|
|
|
<div class="output_text output_subarea ">
|
|
<pre>'Expected Max Drawdown: 4.34%'</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div></p>
|
|
|
|
|
|
|
|
</div>
|
|
<!-- /Content -->
|
|
|
|
<!-- Footer -->
|
|
<div class="footer gradient-2">
|
|
<div class="container footer-container ">
|
|
<div class="row">
|
|
<div class="col-xs-4 col-sm-3 col-md-3 col-lg-3">
|
|
<div class="footer-title"></div>
|
|
<ul class="list-unstyled">
|
|
<li><a href="https://bspeice.github.io/feeds/all.atom.xml" type="application/atom+xml" rel="alternate"></a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-xs-4 col-sm-3 col-md-3 col-lg-3">
|
|
<div class="footer-title"></div>
|
|
<ul class="list-unstyled">
|
|
<li><a href="https://github.com/bspeice" target="_blank">Github</a></li>
|
|
<li><a href="https://www.linkedin.com/in/bradleespeice" target="_blank">LinkedIn</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-xs-4 col-sm-3 col-md-3 col-lg-3">
|
|
</div>
|
|
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3">
|
|
<p class="pull-right text-right">
|
|
<small><em>Proudly powered by <a href="http://docs.getpelican.com/" target="_blank">pelican</a></em></small><br/>
|
|
<small><em>Theme and code by <a href="https://github.com/molivier" target="_blank">molivier</a></em></small><br/>
|
|
<small></small>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /Footer -->
|
|
</body>
|
|
</html> |