Beginner Tutorial
-----------------

Basics
~~~~~~

Alchemist_lib works with three methods:

    - set_weights
    - select_universe
    - handle_data

*set_weights* is used to set the weight that an asset has respect the others within the portfolio. 
The sum of every weight must be close to 1. The ``df`` parameter is the dataframe returned by ``handle_data``.
Must returns a pandas dataframe with two columns: "asset" and "weight", where "asset" is the index.

*select_universe* have to returns a list of assets the strategy will take into consideration.
If you want all the assets traded on a specific exchange just call the ``get_assets`` function of ``alchemist_lib.exchange``.

*handle_data* is the most importat one because it manages the trading logic. The ``universe`` parameter is the list returned by ``select_universe``.
Must returns a pandas dataframe with two columns: "asset" and "alpha", where "asset" is the index.

To start the strategy you just need to instantiate the ``TradingSystem`` class and call the ``run`` method.

Note:
    Remember to 'paper trade' the strategy before going live, it can be done setting ``paper_trading = True``.


First strategy
~~~~~~~~~~~~~~

Lets take a look at a very simple strategy from the ``examples`` directory, ``buyandhold.py``.

Strategy description:
    *Hold a portfolio equally composed by Ethereum and BitcoinCash.*

First of all we must import all the things we need.
::
    from alchemist_lib.portfolio import LongsOnlyPortfolio
    from alchemist_lib.broker import PoloniexBroker
    from alchemist_lib.tradingsystem import TradingSystem
    import alchemist_lib.exchange as exch
    import pandas as pd

Then we select which assets we want to buy and hold. Just ETH and BCH in this example:
::
    def select_universe(session):
        poloniex_assets = exch.get_assets(session = session, exchange_name = "poloniex")

        my_universe = []
        for asset in poloniex_assets:
            if asset.ticker == "ETH" or asset.ticker == "BCH":
                my_universe.append(asset)
        return my_universe

In this case the ``handle_data`` method is useless so lets set a random value for the "alpha" column of the dataframe.
::
    def handle_data(session, universe):
        df = pd.DataFrame(data = {"asset" : universe, "alpha" : 0}, columns = ["asset", "alpha"]).set_index("asset")
        return df

We want to hold two assets (ETH and BCH) so every one must be 50% of the portfolio value.
::
    def set_weights(df):
        df["weight"] = 0.5 
        return df

Make it starts in paper trading mode, every 4 hours.
::
    algo = TradingSystem(name = "BuyAndHold",
                         portfolio = LongsOnlyPortfolio(capital = 0.01),
                         set_weights = set_weights,
                         select_universe = select_universe,
                         handle_data = handle_data,
                         broker = PoloniexBroker(api_key = "APIKEY",
                                                 secret_key = "SECRETKEY"),
                         paper_trading = True)
    algo.run(delay = "4H", frequency = 1)
    

Execution
~~~~~~~~~

Just type:
::
    $ python3 buyandhold.py

A log file called ``buyandhold.log`` will be created.

Example
~~~~~~~

Another example, a little bit more complex is ``emacrossover.py``.

Strategy description:
    *Hold a portfolio composed by top 5 assets by volume whose EMA 10 is above the EMA 21. Rebalance it every hour.*

Code:
::
    from alchemist_lib.portfolio import LongsOnlyPortfolio
    from alchemist_lib.broker import BittrexBroker
    from alchemist_lib.tradingsystem import TradingSystem
    from alchemist_lib.factor import Factor
    import pandas as pd
    import alchemist_lib.exchange as exch


    def set_weights(df):
        alphas_sum = df["alpha"].sum()
        for asset, alpha in zip(df.index.values, df["alpha"]):
            df.loc[asset, "weight"] = alpha / alphas_sum
            
        return df

    def select_universe(session):
        return exch.get_assets(session = session, exchange_name = "bittrex")

    def handle_data(session, universe):
        fct = Factor(session = session)
        prices = fct.history(universe = universe, field = "close", timeframe = "1H", window_length = 21)
        
        ema10 = fct.ExponentialMovingAverage(values = prices, window_length = 10, field = "close").rename(columns = {"ExponentialMovingAverage" : "ema10"})
        ema21 = fct.ExponentialMovingAverage(values = prices, window_length = 21, field = "close").rename(columns = {"ExponentialMovingAverage" : "ema21"})

        concated = pd.concat([ema10, ema21], axis = 1)
        concated = concated.loc[concated["ma10"] > concated["ma21"], :]
        
        vol = fct.history(universe = concated.index.values, field = "volume", timeframe = "1H", window_length = 1)

        df = pd.concat([concated, vol], axis = 1)
        df = df[["volume"]].rename(columns = {"volume" : "alpha"})
        
        if len(df) > 5:
            df = df.sort_values(by = "volume", ascending = False)
            df = df.head(5)
            
        return df


    algo = TradingSystem(name = "MovingAverageCrossover",
                         portfolio = LongsOnlyPortfolio(capital = 0.1),
                         set_weights = set_weights,
                         select_universe = select_universe,
                         handle_data = handle_data,
                         broker = BittrexBroker(api_key = "APIKEY",
                                                secret_key = "SECRETKEY"),
                         paper_trading = True)
    algo.run(delay = "1H", frequency = 1)


To execute it:
::
    $ python3 emacrossover.py
    

Conclusion
~~~~~~~~~~

These were some basic examples of how alchemist_lib works.
Take a look at the ``example`` folder for more examples.
