Ejemplo n.º 1
0
    def test_add_closing_trades(self):
        dates = date_range(start="2015-01-01", periods=20)
        transactions = DataFrame(
            data=[[2, 10, "A"], [-5, 10, "A"], [-1, 10, "B"]],
            columns=["amount", "price", "symbol"],
            index=dates[:3],
        )
        positions = DataFrame(
            data=[[20, 10, 0], [-30, 10, 30], [-60, 0, 30]],
            columns=["A", "B", "cash"],
            index=dates[:3],
        )

        expected_ix = dates[:3].append(
            DatetimeIndex([dates[2] + Timedelta(seconds=1)]))
        expected = DataFrame(
            data=[
                ["A", 2, 10],
                ["A", -5, 10],
                ["B", -1, 10.0],
                [
                    "A",
                    3,
                    20.0,
                ],
            ],
            columns=["symbol", "amount", "price"],
            index=expected_ix,
        )

        transactions_closed = add_closing_transactions(positions, transactions)
        assert_frame_equal(transactions_closed, expected)
Ejemplo n.º 2
0
    def test_txn_pnl_matches_round_trip_pnl(self):
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))

        test_txn = read_csv(gzip.open(
                            __location__ + '/test_data/test_txn.csv.gz'),
                            index_col=0, parse_dates=True)
        test_pos = read_csv(gzip.open(
                            __location__ + '/test_data/test_pos.csv.gz'),
                            index_col=0, parse_dates=True)

        transactions_closed = add_closing_transactions(test_pos, test_txn)
        transactions_closed['txn_dollars'] = transactions_closed.amount * \
            -1. * transactions_closed.price
        round_trips = extract_round_trips(transactions_closed)

        self.assertAlmostEqual(round_trips.pnl.sum(),
                               transactions_closed.txn_dollars.sum())
Ejemplo n.º 3
0
    def test_add_closing_trades(self):
        dates = date_range(start='2015-01-01', periods=20)
        transactions = DataFrame(data=[[2, 10, 'A'], [-5, 10, 'A'],
                                       [-1, 10, 'B']],
                                 columns=['amount', 'price', 'symbol'],
                                 index=[dates[:3]])
        positions = DataFrame(data=[[20, 10, 0], [-30, 10, 30], [-60, 0, 30]],
                              columns=['A', 'B', 'cash'],
                              index=[dates[:3]])

        expected_ix = dates[:3].append(
            DatetimeIndex([dates[2] + Timedelta(seconds=1)]))
        expected = DataFrame(data=[[2, 10, 'A'], [-5, 10, 'A'], [-1, 10., 'B'],
                                   [3, 20., 'A']],
                             columns=['amount', 'price', 'symbol'],
                             index=expected_ix)

        transactions_closed = add_closing_transactions(positions, transactions)
        assert_frame_equal(transactions_closed, expected)
Ejemplo n.º 4
0
    def test_add_closing_trades(self):
        dates = date_range(start='2015-01-01', periods=20)
        transactions = DataFrame(data=[[2, 10, 'A'],
                                       [-5, 10, 'A'],
                                       [-1, 10, 'B']],
                                 columns=['amount', 'price', 'symbol'],
                                 index=[dates[:3]])
        positions = DataFrame(data=[[20, 10, 0],
                                    [-30, 10, 30],
                                    [-60, 0, 30]],
                              columns=['A', 'B', 'cash'],
                              index=[dates[:3]])

        expected_ix = dates[:3].append(DatetimeIndex([dates[2] +
                                                      Timedelta(seconds=1)]))
        expected = DataFrame(data=[[2, 10, 'A'],
                                   [-5, 10, 'A'],
                                   [-1, 10., 'B'],
                                   [3, 20., 'A']],
                             columns=['amount', 'price', 'symbol'],
                             index=expected_ix)

        transactions_closed = add_closing_transactions(positions, transactions)
        assert_frame_equal(transactions_closed, expected)
Ejemplo n.º 5
0
def create_report(perf,
                  filename,
                  now,
                  doc=None,
                  duration=None,
                  param=None,
                  info=None,
                  show_image=True):
    if not hasattr(perf, 'returns'):
        perf['returns'] = perf['pnl'] / (perf['portfolio_value'] - perf['pnl'])
        perf['returns'] = perf['returns'].replace([np.nan, np.inf, -np.inf],
                                                  0.0)

    tot_positions = sum([len(x) for x in perf.positions])
    if tot_positions == 0:
        log.warn("No positions available")
        return

    rets, positions, transactions = pf.utils.extract_rets_pos_txn_from_zipline(
        perf)
    date_rows = OrderedDict()
    if len(rets.index) > 0:
        date_rows['Start date'] = rets.index[0].strftime('%Y-%m-%d')
        date_rows['End date'] = rets.index[-1].strftime('%Y-%m-%d')
        date_rows['Total months'] = int(len(rets) / 21)

    perf_stats_series = pf.timeseries.perf_stats(rets,
                                                 positions=positions,
                                                 transactions=transactions)

    benchmark_rets = returns(symbol('SPY'), rets.index[0], rets.index[-1])
    benchmark_perf_stats = pf.timeseries.perf_stats(benchmark_rets)

    perf_stats_df = pd.DataFrame(perf_stats_series, columns=['Backtest'])
    perf_stats_df['Benchmark'] = benchmark_perf_stats
    perf_stats_df[
        'Spread'] = perf_stats_df['Backtest'] - perf_stats_df['Benchmark']
    format_perf_stats(perf_stats_df)

    drawdown_df = pf.timeseries.gen_drawdown_table(rets, top=5)
    rets_interesting = pf.timeseries.extract_interesting_date_ranges(rets)
    positions = utils.check_intraday('infer', rets, positions, transactions)
    transactions_closed = rt.add_closing_transactions(positions, transactions)
    trades = rt.extract_round_trips(
        transactions_closed,
        portfolio_value=positions.sum(axis='columns') / (1 + rets))

    if show_image:
        fig0 = None
        fig1 = None
        fig2 = None
        fig3 = None
        fig4 = None
        fig5 = None
        try:
            fig0 = create_log_returns_chart(rets, benchmark_rets)
        except Exception as e:
            log.warn(e)

        try:
            fig1 = pf.create_returns_tear_sheet(rets,
                                                positions,
                                                transactions,
                                                benchmark_rets=benchmark_rets,
                                                return_fig=True)
        except Exception as e:
            log.warn(e)

        try:
            fig2 = pf.create_position_tear_sheet(rets,
                                                 positions,
                                                 return_fig=True)
        except Exception as e:
            log.warn(e)

        try:
            fig3 = pf.create_txn_tear_sheet(rets,
                                            positions,
                                            transactions,
                                            return_fig=True)
        except Exception as e:
            log.warn(e)

        try:
            fig4 = pf.create_interesting_times_tear_sheet(rets,
                                                          return_fig=True)
        except Exception as e:
            log.warn(e)

        try:
            fig5 = pf.create_round_trip_tear_sheet(rets,
                                                   positions,
                                                   transactions,
                                                   return_fig=True)
        except Exception as e:
            log.warn(e)

    report_suffix = "_%s_%.2f_report.htm" % (
        now.strftime(DATETIME_FMT), 100. * perf_stats_series['Annual return'])
    reportfile = change_extension(filename, report_suffix)
    with open(reportfile, 'w') as f:
        print("""<!DOCTYPE html>
<html>
   <head>
      <title>Performance Report</title>
      <style >
         body {
         font-family: Arial, Helvetica, sans-serif;
         }
         table {
         border-collapse: collapse;
         }
         tbody tr:nth-child(odd) {
         background-color: lightgrey;
         }
         tbody tr:nth-child(even) {
         background-color: white;
         }
         tr th {
         border: none;
         text-align: right;
         padding: 2px 5px 2px;
         }
         tr td {
         border: none;
         text-align: right;
         padding: 2px 5px 2px;
         }
      </style>
      
      <script type="text/javascript">
        function showElement() {
            element = document.getElementById('code'); 
            element.style.visibility = 'visible'; 
        } 
      
        function hideElement() { 
            element = document.getElementById('code'); 
            element.style.visibility = 'hidden'; 
        } 
      </script> 
   </head>
   <body>""",
              file=f)
        print("<h1>Performance report for " + os.path.basename(filename) +
              "</h1>",
              file=f)
        print("<p>Created on %s</p>" % (now), file=f)
        if duration is not None:
            print("<p>Backtest executed in %s</p>" %
                  (time.strftime("%H:%M:%S", time.gmtime(duration))),
                  file=f)
        if doc is not None:
            print('<h3>Description</h3>', file=f)
            print('<p style="white-space: pre">%s</p>' % doc.strip(), file=f)
        if param is not None and len(param) > 0:
            print('<h3>Parameters</h3>', file=f)
            print('<pre>%s</pre><br/>' % str(param), file=f)
        if info is not None and len(info) > 0:
            print('<h3>Info</h3>', file=f)
            print('<pre>%s</pre><br/>' % str(info), file=f)
        print(to_html_table(perf_stats_df,
                            float_format='{0:.2f}'.format,
                            header_rows=date_rows),
              file=f)
        print("<br/>", file=f)
        if show_image:
            if fig0 is not None:
                print("<h3>Log Returns</h3>", file=f)
                print(_to_img(fig0), file=f)
                print("<br/>", file=f)
        print(to_html_table(
            drawdown_df.sort_values('Net drawdown in %', ascending=False),
            name='Worst drawdown periods',
            float_format='{0:.2f}'.format,
        ),
              file=f)
        print("<br/>", file=f)
        print(to_html_table(pd.DataFrame(rets_interesting).describe().
                            transpose().loc[:, ['mean', 'min', 'max']] * 100,
                            name='Stress Events',
                            float_format='{0:.2f}%'.format),
              file=f)
        print("<br/>", file=f)
        if len(trades) >= 5:
            stats = rt.gen_round_trip_stats(trades)
            print(to_html_table(stats['summary'],
                                float_format='{:.2f}'.format,
                                name='Summary stats'),
                  file=f)
            print("<br/>", file=f)
            print(to_html_table(stats['pnl'],
                                float_format='${:.2f}'.format,
                                name='PnL stats'),
                  file=f)
            print("<br/>", file=f)
            print(to_html_table(stats['duration'],
                                float_format='{:.2f}'.format,
                                name='Duration stats'),
                  file=f)
            print("<br/>", file=f)
            print(to_html_table(stats['returns'] * 100,
                                float_format='{:.2f}%'.format,
                                name='Return stats'),
                  file=f)
            print("<br/>", file=f)
            stats['symbols'].columns = stats['symbols'].columns.map(
                format_asset)
            print(to_html_table(stats['symbols'] * 100,
                                float_format='{:.2f}%'.format,
                                name='Symbol stats'),
                  file=f)

        if show_image:
            if fig1 is not None:
                print("<h3>Returns</h3>", file=f)
                print(_to_img(fig1), file=f)

            if fig2 is not None:
                print("<h3>Positions</h3>", file=f)
                print(_to_img(fig2), file=f)

            if fig3 is not None:
                print("<h3>Transactions</h3>", file=f)
                print(_to_img(fig3), file=f)

            if fig4 is not None:
                print("<h3>Interesting Times</h3>", file=f)
                print(_to_img(fig4), file=f)

            if fig5 is not None:
                print("<h3>Trades</h3>", file=f)
                print(_to_img(fig5), file=f)

        print('<br/>', file=f)
        print(
            '<button onclick="showElement()">Show Code</button> <button onclick="hideElement()">Hide Code</button>',
            file=f)
        print('<pre id="code" style="visibility: hidden">', file=f)
        print(open(filename, "r").read(), file=f)
        print('</pre>', file=f)

        print("</body>\n</html>", file=f)