Metadata-Version: 2.1
Name: anansi-toolkit
Version: 0.1.0
Summary: A tool to analyze data and perform operations in markets
Home-page: https://github.com/marcusmello/anansi.git
License: GPL-3.0-or-later
Keywords: candlesticks,cryptocurrency,stock market,trading bot,finance
Author: Marcus Mello Vintem
Author-email: marcus@vintem.tech
Requires-Python: >=3.8,<4.0
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Requires-Dist: pandas (>=1.0.5,<2.0.0)
Requires-Dist: pendulum (>=2.1.0,<3.0.0)
Requires-Dist: pony (>=0.7.13,<0.8.0)
Requires-Dist: requests (>=2.24.0,<3.0.0)
Requires-Dist: requests_mock (>=1.8.0,<2.0.0)
Project-URL: Repository, https://gitlab.com/marcusmello/anansi.git
Description-Content-Type: text/markdown

# Anansi

## Dependencies

Python, Pip, Poetry.

To install [poetry](https://python-poetry.org/docs/#installation), on
osx, linux or *bashonwindows* terminals, type it:

    curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

Alternatively, poetry could be installed by pip (supposing you have
python and pip already installed):

    pip install poetry

## Consuming on Jupyter notebook

**That is only a suggestion, you could run anansi on any python
terminal. Only tested on linux.**

Perform the commands:

    poetry install
    poetry run python -m ipykernel install --user --name=$(basename $(pwd))
    poetry run jupyter notebook > jupyterlog 2>&1 &

## Straight to the point: Running Default Back Testing Operation

### Importing Dependencies

```python
from anansi.tradingbot.models import *
from anansi.tradingbot import traders
from anansi.tradingbot.views import create_user, create_default_operation
```

### Add a new user

```python
my_user_first_name = "John"

create_user(first_name=my_user_first_name,
                   last_name="Doe",
                   email = "{}@email.com".format(my_user_first_name.lower()))
```

### Creating a default operation

```python
my_user = User[1]
create_default_operation(user=my_user)
```

### Instantiating a trader

```python
my_op = Operation.get(id=1)
my_trader = traders.DefaultTrader(operation=my_op)
```

### Run the trader

```python
my_trader.run()
```

## Playing with the database models

### Getting all users

```python
users = select(user for user in User)
users.show()
```

    id|first_name|last_name|login_displayed_name|email         
    --+----------+---------+--------------------+--------------
    1 |John      |Doe      |                    |john@email.com

```python
my_user.first_name
```

    'John'

### Some operation attribute

```python
my_op.stop_loss.name
```

    'StopTrailing3T'

### Some trader attribute

```python
my_trader.Classifier.parameters.time_frame
```

    '6h'

### Updating some attributes

```python
before_update = my_trader.operation.position.side, my_trader.operation.position.exit_reference_price

my_trader.operation.position.update(side="Long", exit_reference_price=1020.94)

after_update = my_trader.operation.position.side, my_trader.operation.position.exit_reference_price

before_update, after_update
```

    (('Zeroed', None), ('Long', 1020.94))

## Requesting klines

### Klines treated and ready for use, including market indicators methods

The example below uses the 'KlinesFromBroker' class from the 'handlers'
module ('marketdata' package), which works as an abstraction over the
data brokers, not only serializing requests (in order to respect
brokers' limits), but also conforming the klines like a pandas
dataframe,
[extended](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.api.extensions.register_dataframe_accessor.html)
with market indicator methods.

```python
from anansi.marketdata.handlers import KlinesFromBroker
```

```python
BinanceKlines = KlinesFromBroker(
  broker_name="binance", ticker_symbol="BTCUSDT", time_frame="1h")
```

```python
newest_klines = BinanceKlines.newest(2167)
```

```python
newest_klines
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open_time</th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Volume</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2020-06-17 11:00:00</td>
      <td>9483.25</td>
      <td>9511.53</td>
      <td>9466.00</td>
      <td>9478.61</td>
      <td>1251.802697</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2020-06-17 12:00:00</td>
      <td>9478.61</td>
      <td>9510.88</td>
      <td>9477.35</td>
      <td>9499.25</td>
      <td>1120.426332</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2020-06-17 13:00:00</td>
      <td>9499.24</td>
      <td>9565.00</td>
      <td>9432.00</td>
      <td>9443.48</td>
      <td>4401.693008</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2020-06-17 14:00:00</td>
      <td>9442.50</td>
      <td>9464.83</td>
      <td>9366.09</td>
      <td>9410.95</td>
      <td>4802.211120</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2020-06-17 15:00:00</td>
      <td>9411.27</td>
      <td>9436.54</td>
      <td>9388.43</td>
      <td>9399.24</td>
      <td>2077.135281</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>2162</th>
      <td>2020-09-15 13:00:00</td>
      <td>10907.94</td>
      <td>10917.96</td>
      <td>10834.00</td>
      <td>10834.71</td>
      <td>3326.420940</td>
    </tr>
    <tr>
      <th>2163</th>
      <td>2020-09-15 14:00:00</td>
      <td>10834.71</td>
      <td>10879.00</td>
      <td>10736.63</td>
      <td>10764.19</td>
      <td>4382.021477</td>
    </tr>
    <tr>
      <th>2164</th>
      <td>2020-09-15 15:00:00</td>
      <td>10763.37</td>
      <td>10815.47</td>
      <td>10745.63</td>
      <td>10784.46</td>
      <td>3531.309654</td>
    </tr>
    <tr>
      <th>2165</th>
      <td>2020-09-15 16:00:00</td>
      <td>10785.23</td>
      <td>10827.61</td>
      <td>10700.00</td>
      <td>10784.23</td>
      <td>3348.735166</td>
    </tr>
    <tr>
      <th>2166</th>
      <td>2020-09-15 17:00:00</td>
      <td>10784.23</td>
      <td>10812.44</td>
      <td>10738.33</td>
      <td>10794.84</td>
      <td>1931.035921</td>
    </tr>
  </tbody>
</table>
<p>2167 rows × 6 columns</p>
</div>

### Applying simple moving average  indicators

```python
indicator = newest_klines.apply_indicator.trend.simple_moving_average(number_of_candles=35)
```

```python
indicator.name, indicator.last(), indicator.serie
```

    ('sma_ohlc4_35',
     10669.49407142858,
     0                NaN
     1                NaN
     2                NaN
     3                NaN
     4                NaN
                 ...     
     2162    10619.190500
     2163    10632.213571
     2164    10644.682643
     2165    10657.128857
     2166    10669.494071
     Length: 2167, dtype: float64)

```python
newest_klines
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open_time</th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Volume</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2020-06-17 11:00:00</td>
      <td>9483.25</td>
      <td>9511.53</td>
      <td>9466.00</td>
      <td>9478.61</td>
      <td>1251.802697</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2020-06-17 12:00:00</td>
      <td>9478.61</td>
      <td>9510.88</td>
      <td>9477.35</td>
      <td>9499.25</td>
      <td>1120.426332</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2020-06-17 13:00:00</td>
      <td>9499.24</td>
      <td>9565.00</td>
      <td>9432.00</td>
      <td>9443.48</td>
      <td>4401.693008</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2020-06-17 14:00:00</td>
      <td>9442.50</td>
      <td>9464.83</td>
      <td>9366.09</td>
      <td>9410.95</td>
      <td>4802.211120</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2020-06-17 15:00:00</td>
      <td>9411.27</td>
      <td>9436.54</td>
      <td>9388.43</td>
      <td>9399.24</td>
      <td>2077.135281</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>2162</th>
      <td>2020-09-15 13:00:00</td>
      <td>10907.94</td>
      <td>10917.96</td>
      <td>10834.00</td>
      <td>10834.71</td>
      <td>3326.420940</td>
    </tr>
    <tr>
      <th>2163</th>
      <td>2020-09-15 14:00:00</td>
      <td>10834.71</td>
      <td>10879.00</td>
      <td>10736.63</td>
      <td>10764.19</td>
      <td>4382.021477</td>
    </tr>
    <tr>
      <th>2164</th>
      <td>2020-09-15 15:00:00</td>
      <td>10763.37</td>
      <td>10815.47</td>
      <td>10745.63</td>
      <td>10784.46</td>
      <td>3531.309654</td>
    </tr>
    <tr>
      <th>2165</th>
      <td>2020-09-15 16:00:00</td>
      <td>10785.23</td>
      <td>10827.61</td>
      <td>10700.00</td>
      <td>10784.23</td>
      <td>3348.735166</td>
    </tr>
    <tr>
      <th>2166</th>
      <td>2020-09-15 17:00:00</td>
      <td>10784.23</td>
      <td>10812.44</td>
      <td>10738.33</td>
      <td>10794.84</td>
      <td>1931.035921</td>
    </tr>
  </tbody>
</table>
<p>2167 rows × 6 columns</p>
</div>

### Same as above, but showing indicator column

```python
indicator = newest_klines.apply_indicator.trend.simple_moving_average(
  number_of_candles=35, indicator_column="SMA_OHLC4_n35")
```

```python
newest_klines
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open_time</th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Volume</th>
      <th>SMA_OHLC4_n35</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2020-06-17 11:00:00</td>
      <td>9483.25</td>
      <td>9511.53</td>
      <td>9466.00</td>
      <td>9478.61</td>
      <td>1251.802697</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2020-06-17 12:00:00</td>
      <td>9478.61</td>
      <td>9510.88</td>
      <td>9477.35</td>
      <td>9499.25</td>
      <td>1120.426332</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2020-06-17 13:00:00</td>
      <td>9499.24</td>
      <td>9565.00</td>
      <td>9432.00</td>
      <td>9443.48</td>
      <td>4401.693008</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2020-06-17 14:00:00</td>
      <td>9442.50</td>
      <td>9464.83</td>
      <td>9366.09</td>
      <td>9410.95</td>
      <td>4802.211120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2020-06-17 15:00:00</td>
      <td>9411.27</td>
      <td>9436.54</td>
      <td>9388.43</td>
      <td>9399.24</td>
      <td>2077.135281</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>2162</th>
      <td>2020-09-15 13:00:00</td>
      <td>10907.94</td>
      <td>10917.96</td>
      <td>10834.00</td>
      <td>10834.71</td>
      <td>3326.420940</td>
      <td>10619.190500</td>
    </tr>
    <tr>
      <th>2163</th>
      <td>2020-09-15 14:00:00</td>
      <td>10834.71</td>
      <td>10879.00</td>
      <td>10736.63</td>
      <td>10764.19</td>
      <td>4382.021477</td>
      <td>10632.213571</td>
    </tr>
    <tr>
      <th>2164</th>
      <td>2020-09-15 15:00:00</td>
      <td>10763.37</td>
      <td>10815.47</td>
      <td>10745.63</td>
      <td>10784.46</td>
      <td>3531.309654</td>
      <td>10644.682643</td>
    </tr>
    <tr>
      <th>2165</th>
      <td>2020-09-15 16:00:00</td>
      <td>10785.23</td>
      <td>10827.61</td>
      <td>10700.00</td>
      <td>10784.23</td>
      <td>3348.735166</td>
      <td>10657.128857</td>
    </tr>
    <tr>
      <th>2166</th>
      <td>2020-09-15 17:00:00</td>
      <td>10784.23</td>
      <td>10812.44</td>
      <td>10738.33</td>
      <td>10794.84</td>
      <td>1931.035921</td>
      <td>10669.494071</td>
    </tr>
  </tbody>
</table>
<p>2167 rows × 7 columns</p>
</div>

### Raw klines, using the low level abstraction module "*data_brokers*"

**DISCLAIMER: Requests here are not queued! There is a risk of banning
the IP or even blocking API keys if some limits are exceeded. Use with
caution.**

```python
from anansi.marketdata import data_brokers
```

```python
BinanceBroker = data_brokers.BinanceDataBroker()
```

```python
my_klines = BinanceBroker.get_klines(ticker_symbol="BTCUSDT", time_frame="1m")
```

```python
my_klines
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open_time</th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Volume</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>1600165560</td>
      <td>10688.12</td>
      <td>10691.14</td>
      <td>10684.88</td>
      <td>10684.88</td>
      <td>21.529835</td>
    </tr>
    <tr>
      <th>1</th>
      <td>1600165620</td>
      <td>10684.88</td>
      <td>10686.15</td>
      <td>10681.84</td>
      <td>10685.99</td>
      <td>18.487428</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1600165680</td>
      <td>10686.00</td>
      <td>10687.65</td>
      <td>10684.92</td>
      <td>10687.09</td>
      <td>22.246376</td>
    </tr>
    <tr>
      <th>3</th>
      <td>1600165740</td>
      <td>10687.09</td>
      <td>10689.54</td>
      <td>10683.86</td>
      <td>10687.26</td>
      <td>18.818481</td>
    </tr>
    <tr>
      <th>4</th>
      <td>1600165800</td>
      <td>10687.26</td>
      <td>10687.26</td>
      <td>10683.71</td>
      <td>10685.76</td>
      <td>38.281582</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>494</th>
      <td>1600195200</td>
      <td>10762.43</td>
      <td>10763.48</td>
      <td>10760.35</td>
      <td>10760.75</td>
      <td>8.572210</td>
    </tr>
    <tr>
      <th>495</th>
      <td>1600195260</td>
      <td>10760.75</td>
      <td>10762.48</td>
      <td>10759.30</td>
      <td>10759.31</td>
      <td>11.089815</td>
    </tr>
    <tr>
      <th>496</th>
      <td>1600195320</td>
      <td>10759.30</td>
      <td>10762.22</td>
      <td>10755.39</td>
      <td>10761.26</td>
      <td>27.070820</td>
    </tr>
    <tr>
      <th>497</th>
      <td>1600195380</td>
      <td>10761.26</td>
      <td>10761.26</td>
      <td>10751.74</td>
      <td>10756.02</td>
      <td>15.482246</td>
    </tr>
    <tr>
      <th>498</th>
      <td>1600195440</td>
      <td>10755.61</td>
      <td>10756.57</td>
      <td>10748.03</td>
      <td>10748.04</td>
      <td>61.153777</td>
    </tr>
  </tbody>
</table>
<p>499 rows × 6 columns</p>
</div>

### Same as above, but returning all information get from the data broker

```python
my_klines = BinanceBroker.get_klines(ticker_symbol="BTCUSDT", time_frame="1m", show_only_desired_info=False)
```

```python
my_klines
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open_time</th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Volume</th>
      <th>Close_time</th>
      <th>Quote_asset_volume</th>
      <th>Number_of_trades</th>
      <th>Taker_buy_base_asset_volume</th>
      <th>Taker_buy_quote_asset_volume</th>
      <th>Ignore</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>1600165560</td>
      <td>10688.12</td>
      <td>10691.14</td>
      <td>10684.88</td>
      <td>10684.88</td>
      <td>21.529835</td>
      <td>1600165619</td>
      <td>230126.587773</td>
      <td>373.0</td>
      <td>10.279415</td>
      <td>109864.149822</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>1600165620</td>
      <td>10684.88</td>
      <td>10686.15</td>
      <td>10681.84</td>
      <td>10685.99</td>
      <td>18.487428</td>
      <td>1600165679</td>
      <td>197536.180849</td>
      <td>336.0</td>
      <td>8.256498</td>
      <td>88223.566054</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1600165680</td>
      <td>10686.00</td>
      <td>10687.65</td>
      <td>10684.92</td>
      <td>10687.09</td>
      <td>22.246376</td>
      <td>1600165739</td>
      <td>237738.839831</td>
      <td>415.0</td>
      <td>13.378805</td>
      <td>142975.243246</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>1600165740</td>
      <td>10687.09</td>
      <td>10689.54</td>
      <td>10683.86</td>
      <td>10687.26</td>
      <td>18.818481</td>
      <td>1600165799</td>
      <td>201100.293663</td>
      <td>539.0</td>
      <td>9.062957</td>
      <td>96849.611844</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>1600165800</td>
      <td>10687.26</td>
      <td>10687.26</td>
      <td>10683.71</td>
      <td>10685.76</td>
      <td>38.281582</td>
      <td>1600165859</td>
      <td>409068.511314</td>
      <td>534.0</td>
      <td>16.799813</td>
      <td>179523.708531</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>494</th>
      <td>1600195200</td>
      <td>10762.43</td>
      <td>10763.48</td>
      <td>10760.35</td>
      <td>10760.75</td>
      <td>8.572210</td>
      <td>1600195259</td>
      <td>92253.016477</td>
      <td>292.0</td>
      <td>2.394778</td>
      <td>25771.715413</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>495</th>
      <td>1600195260</td>
      <td>10760.75</td>
      <td>10762.48</td>
      <td>10759.30</td>
      <td>10759.31</td>
      <td>11.089815</td>
      <td>1600195319</td>
      <td>119341.014647</td>
      <td>277.0</td>
      <td>3.064458</td>
      <td>32976.256534</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>496</th>
      <td>1600195320</td>
      <td>10759.30</td>
      <td>10762.22</td>
      <td>10755.39</td>
      <td>10761.26</td>
      <td>27.070820</td>
      <td>1600195379</td>
      <td>291245.877535</td>
      <td>490.0</td>
      <td>14.654896</td>
      <td>157679.926758</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>497</th>
      <td>1600195380</td>
      <td>10761.26</td>
      <td>10761.26</td>
      <td>10751.74</td>
      <td>10756.02</td>
      <td>15.482246</td>
      <td>1600195439</td>
      <td>166520.446192</td>
      <td>353.0</td>
      <td>7.390407</td>
      <td>79491.160961</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>498</th>
      <td>1600195440</td>
      <td>10755.61</td>
      <td>10756.57</td>
      <td>10748.03</td>
      <td>10748.04</td>
      <td>61.153777</td>
      <td>1600195499</td>
      <td>657520.935924</td>
      <td>585.0</td>
      <td>13.436657</td>
      <td>144474.084684</td>
      <td>0.0</td>
    </tr>
  </tbody>
</table>
<p>499 rows × 12 columns</p>
</div>

