<jupyter_start><jupyter_text>Moving average crossover Strategy- strategy: `script/strategy.py -> mac()`- generate signals- backtest: `script/backtest.py -> bt()`- evaluation: **Sharpe ratio**,..., etc.<jupyter_code>import pandas as pd
import numpy as np
data_folder = "./data/"
crypto_df = pd.read_csv(data_folder + 'train.csv')
asset_details = pd.read_csv(data_folder + 'asset_details.csv')<jupyter_output><empty_output><jupyter_text>Trading rule details- Use **BTC** for testing the strategy.- create two separate Simple Moving Averages (SMA) of a time series with differing lookback periods,    let’s say, 40 days and 100 days. - long moving tends toward short moving.- If the short moving average exceeds the long moving average then you go long.- if the long moving average exceeds the short moving average then you exit.- Only long/sell once if consecutive signal occurs.- ignore the transaction fee for now.<jupyter_code>btc = crypto_df[crypto_df["Asset_ID"]== 1 ]
btc<jupyter_output><empty_output><jupyter_text>Generate signals for daily BTC- use daily BTC close price as the asset price to trade with.- signal code '1' short moving average exceeds the long moving average, signal code '0' otherwise.- visualize the signals that '^' for "buying" and 'v' for "selling".<jupyter_code>from script.strategy import mac
from script.morestats import ohlcv_with_frequency
btc_daily = ohlcv_with_frequency(df = btc,frequency='1D')
signals = mac(asset_df=btc_daily,
                price_col='Close', short_window=40,long_window=100, plot_signal=True)
signals.head()<jupyter_output>/Users/dingxian/Documents/GitHub/Crypto_Forecasting_kaggle/script/morestats.py:29: FutureWarning: casting datetime64[ns] values to int64 with .astype(...) is deprecated and will raise in a future version. Use .view(...) instead.
  t = date_str.astype('int64') // 10**9 ##unix time with nanoseconds //10**9<jupyter_text>Backtesting on daily BTC- We buy or sell the fixed share once on the first signal among consecutive same signals.- The share to buy or sell every time is fixed as 100 unit(level doesn't matter when fixed).- Initial capital to play is 100000 USD.- Visualize the account balance change.<jupyter_code>from script.backtest import bt
portfolio = bt(asset_df=btc_daily, signals=signals, strategy='mac',
                initial_capital = float(100000.0), price_col= 'Close', 
                shares_signal=100, plot_balance=True)
portfolio.head()<jupyter_output><empty_output><jupyter_text>Evaluate the strategy- Sharpe ratio: the ratio between the returns and the additional risk that is incurred is quite OK. Usually, a ratio greater than 1 is acceptable by investors, 2 is very good and 3 is excellent. $$S_{a}=\frac{E\left[R_{a}-R_{risk free}\right]}{\sigma_{a}}$$- Maximum Drawdown: the largest single drop from peak to bottom in the value of a portfolio before a new peak is achieved.- Compound Annual Growth Rate (CAGR): $$(EV / BV)^{1 / n}-1$$- distribution of returns- trade-level metrics<jupyter_code>returns = portfolio['returns']
# annualized Sharpe ratio, BTC market opens everyday
daily_sharpe =(returns.mean() - 0 )/ returns.std()
sharpe_ratio = np.sqrt(365) * daily_sharpe
sharpe_ratio<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10269934843313683, 'fraction_numerical': 0.017375116351225565, 'mean_word_length': 5.106060606060606, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '344882', 'license': 'MIT', 'n_tokens_mistral': 1016, 'n_tokens_neox': 933, 'n_words': 347, 'path': 'MA_cross_strategy.ipynb', 'repo_name': 'monchewharry/Crypto_Forecasting_kaggle', 'size': '3223'}