Metadata-Version: 2.1
Name: positions-backtester
Version: 0.1.4
Summary: Package to backtest trading strategies (dataframe with positions) with execution costs modeling
Home-page: https://github.com/stas-prokopiev/positions_backtester
License: MIT
Author: stanislav
Author-email: stas.prokopiev@gmail.com
Requires-Python: >=3.7,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Requires-Dist: pandas (>=1.4.0,<2.0.0)
Requires-Dist: tqdm (>=4.64.0,<5.0.0)
Project-URL: Repository, https://github.com/stas-prokopiev/positions_backtester
Description-Content-Type: text/x-rst

=====================
positions_backtester
=====================

.. image:: https://img.shields.io/github/last-commit/stas-prokopiev/positions_backtester
   :target: https://img.shields.io/github/last-commit/stas-prokopiev/positions_backtester
   :alt: GitHub last commit

.. image:: https://img.shields.io/github/license/stas-prokopiev/positions_backtester
    :target: https://github.com/stas-prokopiev/positions_backtester/blob/master/LICENSE.txt
    :alt: GitHub license<space><space>

.. image:: https://img.shields.io/pypi/v/positions_backtester
   :target: https://img.shields.io/pypi/v/positions_backtester
   :alt: PyPI

.. image:: https://img.shields.io/pypi/pyversions/positions_backtester
   :target: https://img.shields.io/pypi/pyversions/positions_backtester
   :alt: PyPI - Python Version


.. contents:: **Table of Contents**

Short Overview.
=========================
positions_backtester is a python package (**py>=3.7**) to backtest trading strategies (dataframe with positions) with execution costs modeling

| This package is trying to solve a problem of slow trading with fast data.
| Let's say that you want to update your trading position once in a hour, day, week, ...
| But you have data with much higher time resolution - minutes, seconds, miliseconds
| Then you can give the wanted positions dataframe with the tick with which you want to trade
| And higher resolution will be used to calculate approximate execution prices
| (Which are just the mean price over the choosen execution time period)

Installation via pip:
======================

.. code-block:: bash

    pip install positions_backtester

How to use it
===========================

How to backtest your dataframe with positions
-----------------------------------------------

.. code-block:: python

    from positions_backtester import run_backtest

    df_backtest_res = run_backtest(
        df_positions_short : pd.DataFrame,
        df_execution_prices_full : pd.DataFrame,
        is_to_neutralize : bool=True,
        td_trading_delay : Optional[datetime.timedelta]=None,
        td_execution_duration : Optional[datetime.timedelta]=None,
        const_trading_fees_percent : float=0.01,
    )

!!! **df_execution_prices_full should have the same indices as df_positions_short**


Arguments:

#. **df_positions_short**:
    | pd.DataFrame
    | Positions we want to take with the frequency with which we want to change our positions
#. **df_execution_prices_full**:
    | pd.DataFrame
    | Prices of assets in higher resolution
    | Higher resolution needed for more pricise execution evaluation
#. **is_to_neutralize=True,**:
    | bool
    | Flag if to have long-short equal positions
#. **td_trading_delay=None**:
    | datetime.timedelta
    | Delay needed to calculate the wanted positions
#. **td_execution_duration**:
    | datetime.timedelta
    | How long should the execution take
    | Execution price will be the mean price over execution time period
#. **const_trading_fees_percent**:
    | float
    | Broker trading fees

Inputs:
-----------------------------------------------

df_positions_short
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

..
    This is a comment

    .. raw:: html

    <embed>
        <table border="1" class="dataframe">
        <thead>
            <tr style="text-align: right;">
            <th></th>
            <th>asset_1</th>
            <th>asset_2</th>
            <th>asset_3</th>
            </tr>
            <tr>
            <th>Close datetime</th>
            <th></th>
            <th></th>
            <th></th>
            </tr>
        </thead>
        <tbody>
            <tr>
            <th>2021-07-06 22:00:00+00:00</th>
            <td>0.285602</td>
            <td>NaN</td>
            <td>NaN</td>
            </tr>
            <tr>
            <th>2021-07-06 23:00:00+00:00</th>
            <td>0.296204</td>
            <td>NaN</td>
            <td>NaN</td>
            </tr>
            <tr>
            <th>2021-07-07 00:00:00+00:00</th>
            <td>0.294426</td>
            <td>NaN</td>
            <td>NaN</td>
            </tr>
        </tbody>
        </table>
    </embed>


df_prices_full
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

..
    This is a comment
    .. raw:: html

    <embed>
        <table border="1" class="dataframe">
        <thead>
            <tr style="text-align: right;">
            <th></th>
            <th>asset_1</th>
            <th>asset_2</th>
            <th>asset_3</th>
            </tr>
            <tr>
            <th>Close datetime</th>
            <th></th>
            <th></th>
            <th></th>
            </tr>
        </thead>
        <tbody>
            <tr>
            <th>2021-07-06 23:57:00+00:00</th>
            <td>317.86</td>
            <td>57.00</td>
            <td>15.488</td>
            </tr>
            <tr>
            <th>2021-07-06 23:58:00+00:00</th>
            <td>317.11</td>
            <td>57.04</td>
            <td>15.480</td>
            </tr>
            <tr>
            <th>2021-07-06 23:59:00+00:00</th>
            <td>316.49</td>
            <td>57.01</td>
            <td>15.459</td>
            </tr>
        </tbody>
        </table>
    </embed>


Output: df_backtest_res
-----------------------------------------------

..
    This is a comment
    .. raw:: html

    <embed>
        <table border="1" class="dataframe">
        <thead>
            <tr style="text-align: right;">
            <th></th>
            <th>PNL before_costs</th>
            <th>PNL execution_fee</th>
            <th>PNL const_trading_fee</th>
            <th>PNL after_costs</th>
            <th>PNL half_costs</th>
            <th>trading_volume</th>
            <th>booksize</th>
            <th>max weight</th>
            <th>long count</th>
            <th>short count</th>
            </tr>
            <tr>
            <th>Close datetime</th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            </tr>
        </thead>
        <tbody>
            <tr>
            <th>2021-07-06 20:00:00+00:00</th>
            <td>-0.002108</td>
            <td>-0.004361</td>
            <td>0.000003</td>
            <td>0.002250</td>
            <td>0.000071</td>
            <td>0.034720</td>
            <td>1.0</td>
            <td>0.14</td>
            <td>33</td>
            <td>200</td>
            <td>0.5</td>
            <td>0.5</td>
            </tr>
            <tr>
            <th>2021-07-06 21:00:00+00:00</th>
            <td>-0.005282</td>
            <td>-0.000222</td>
            <td>0.000005</td>
            <td>-0.005065</td>
            <td>-0.005174</td>
            <td>0.053568</td>
            <td>1.0</td>
            <td>0.11</td>
            <td>32</td>
            <td>198</td>
            <td>0.5</td>
            <td>0.5</td>
            </tr>
        </tbody>
        </table>
    </embed>


Formulas
===========================

| PNL before_costs = (previous_position) * (price_change_%)
| trading_volume = abs(new_wanted_position - previous_position)
| PNL const_trading_fee = trading_volume * broker_commision
| PNL execution_fee = (new_wanted_position - previous_position) * (execution_price - current_price)
| PNL after_costs = PNL before_costs - (PNL const_trading_fee + PNL execution_fee)
| PNL half_costs = PNL before_costs - (PNL const_trading_fee + PNL execution_fee) / 2.0

Links
=====

    * `PYPI <https://pypi.org/project/positions_backtester/>`_
    * `GitHub <https://github.com/stas-prokopiev/positions_backtester>`_

Project local Links
===================

    * `CHANGELOG <https://github.com/stas-prokopiev/positions_backtester/blob/master/CHANGELOG.rst>`_.
    * `CONTRIBUTING <https://github.com/stas-prokopiev/positions_backtester/blob/master/CONTRIBUTING.rst>`_.

Contacts
========

    * Email: stas.prokopiev@gmail.com
    * `vk.com <https://vk.com/stas.prokopyev>`_
    * `Facebook <https://www.facebook.com/profile.php?id=100009380530321>`_

License
=======

This project is licensed under the MIT License.
