Modify an example strategy to trade on the futures market
-
Help me in modifying this strategy to use it in the futures markets, not the cryptofutures one.
import xarray as xr import qnt.backtester as qnbt import qnt.data as qndata import numpy as np import pandas as pd def load_data(period): futures = qndata.futures.load_data(tail=period, assets=["F_O", "F_LN"]) crypto = qndata.cryptofutures.load_data(tail=period) return {"futures": futures, "crypto": crypto}, futures.time.values def build_data_for_one_step(data, max_date: np.datetime64, lookback_period: int): min_date = max_date - np.timedelta64(lookback_period, "D") return { "futures": data["futures"].sel(time=slice(min_date, max_date)), "crypto": data["crypto"].sel(time=slice(min_date, max_date)), } def predict_weights(market_data): def get_ml_model(): from sklearn.linear_model import RidgeClassifier model = RidgeClassifier(random_state=18) return model def get_features(data): def remove_trend(prices_pandas_): prices_pandas = prices_pandas_.copy(True) assets = prices_pandas.columns for asset in assets: prices_pandas[asset] = np.log(prices_pandas[asset]) return prices_pandas price = data.sel(field="close").ffill('time').bfill('time').fillna(0) # fill NaN for_result = price.to_pandas() features_no_trend_df = remove_trend(for_result) return features_no_trend_df def get_target_classes(data): price_current = data.sel(field="close").dropna('time') price_future = price_current.shift(time=-1).dropna('time') class_positive = 1 class_negative = 0 target_is_price_up = xr.where(price_future > price_current, class_positive, class_negative) return target_is_price_up.to_pandas() futures = market_data["futures"].copy(True) crypto = market_data["crypto"].copy(True) asset_name_all = crypto.coords['asset'].values features_all_df = get_features(futures) target_all_df = get_target_classes(crypto) predict_weights_next_day_df = crypto.sel(field="close").isel(time=-1).to_pandas() for asset_name in asset_name_all: target_for_learn_df = target_all_df[asset_name] feature_for_learn_df = features_all_df[:-1] # last value reserved for prediction # align features and targets target_for_learn_df, feature_for_learn_df = target_for_learn_df.align(feature_for_learn_df, axis=0, join='inner') model = get_ml_model() try: model.fit(feature_for_learn_df.values, target_for_learn_df) feature_for_predict_df = features_all_df[-1:] predict = model.predict(feature_for_predict_df.values) predict_weights_next_day_df[asset_name] = predict except: logging.exception("model failed") # if there is exception, return zero values return xr.zeros_like(crypto.isel(field=0, time=0)) return predict_weights_next_day_df.to_xarray() weights = qnbt.backtest( competition_type="cryptofutures", load_data=load_data, lookback_period=18, start_date='2014-01-01', strategy=predict_weights, window=build_data_for_one_step, analyze=True, build_plots=True )```
-
@magenta-grimer I tried to change some values, like:
competition_type="cryptofutures",
in
competition_type="futures",
and other lines of code before, but I get errors...
Also from the original strategy it seems that we use futures data to predict the crypto prices,
we could try using both other futures data or even cryoto data to predict futures prices and submit it to the future competition?Thanks
-
@magenta-grimer The problem is connected with the fact that the futures competition needs data since January 1st, 2006 (beginning of the in-sample period); the crypto contest needs data since January 1st, 2014.
As a result it is ok to use futures data for predicting the crypto futures data, as the latter has a shorter time series, but the length of the crypto futures data is too short for predicting all futures data.
-
Hello.
If you changed only this line:
competition_type="futures",
you, probably, got the error
min() arg is an empty sequence
It means, that the backtester can't calculate statistics because you return the output with the asset 'BTC' and the futures dataset does not contain this asset. You need to return the output with an asset which the futures dataset contains.
This a working example (see the lines with
###
) :import xarray as xr import qnt.backtester as qnbt import qnt.data as qndata import numpy as np import pandas as pd def load_data(period): futures = qndata.futures.load_data(tail=period, assets=["F_O", "F_LN"]) crypto = qndata.cryptofutures.load_data(tail=period) return {"futures": futures, "crypto": crypto}, futures.time.values def build_data_for_one_step(data, max_date: np.datetime64, lookback_period: int): min_date = max_date - np.timedelta64(lookback_period, "D") return { "futures": data["futures"].sel(time=slice(min_date, max_date)), "crypto": data["crypto"].sel(time=slice(min_date, max_date)), } def predict_weights(market_data): def get_ml_model(): from sklearn.linear_model import RidgeClassifier model = RidgeClassifier(random_state=18) return model def get_features(data): def remove_trend(prices_pandas_): prices_pandas = prices_pandas_.copy(True) assets = prices_pandas.columns for asset in assets: prices_pandas[asset] = np.log(prices_pandas[asset]) return prices_pandas price = data.sel(field="close").ffill('time').bfill('time').fillna(0) # fill NaN for_result = price.to_pandas() features_no_trend_df = remove_trend(for_result) return features_no_trend_df def get_target_classes(data): price_current = data.sel(field="close").dropna('time') price_future = price_current.shift(time=-1).dropna('time') class_positive = 1 class_negative = 0 target_is_price_up = xr.where(price_future > price_current, class_positive, class_negative) return target_is_price_up.to_pandas() futures = market_data["futures"].copy(True) crypto = market_data["crypto"].copy(True) asset_name_all = crypto.coords['asset'].values features_all_df = get_features(futures) target_all_df = get_target_classes(crypto) predict_weights_next_day_df = crypto.sel(field="close").isel(time=-1).to_pandas() for asset_name in asset_name_all: target_for_learn_df = target_all_df[asset_name] feature_for_learn_df = features_all_df[:-1] # last value reserved for prediction # align features and targets target_for_learn_df, feature_for_learn_df = target_for_learn_df.align(feature_for_learn_df, axis=0, join='inner') model = get_ml_model() try: model.fit(feature_for_learn_df.values, target_for_learn_df) feature_for_predict_df = features_all_df[-1:] predict = model.predict(feature_for_predict_df.values) predict_weights_next_day_df[asset_name] = predict except: logging.exception("model failed") # if there is exception, return zero values return xr.zeros_like(crypto.isel(field=0, time=0)) output = predict_weights_next_day_df.to_xarray() ### output = output.assign_coords(asset=['F_DX']) ### return output ### weights = qnbt.backtest( competition_type="futures", load_data=load_data, lookback_period=18, start_date='2014-01-01', strategy=predict_weights, window=build_data_for_one_step, analyze=True, build_plots=True )
And yes, @jeppe_and said is right. It will be impossible to develop a futures strategy using the bitcoin market data because the bitcoin futures contracts and bitcoin itself are very young. The data time series starts from 2013. The in-sample period for the futures contest should start from 2006.
Regards.
-
This post is deleted! -
@support said in Modify an example strategy to trade on the futures market:
Ok, is it possible to use a simple technical strategy for the dates before 1-1-2014 and then switch to the ML strategy? Can you help in coding it?
Thanks
-
Hello. This is such an example:
import xarray as xr import qnt.backtester as qnbt import qnt.data as qndata import numpy as np import pandas as pd import qnt.ta as qnta def load_data(period): futures = qndata.futures.load_data(tail=period, assets=["F_NQ", "F_DX"]) try: # this will fail when there is no data crypto = qndata.cryptofutures.load_data(tail=period, assets=["BTC"]) except: crypto = None return {"futures": futures, "crypto": crypto}, futures.time.values def build_data_for_one_step(data, max_date: np.datetime64, lookback_period: int): min_date = max_date - np.timedelta64(lookback_period, "D") futures = data["futures"].sel(time=slice(min_date, max_date)).copy(True) try: crypto = data["crypto"].sel(time=slice(min_date, max_date)).copy(True) except: crypto = None return { "futures": futures, "crypto": crypto, } def predict_weights(market_data): def get_ml_model(): from sklearn.linear_model import RidgeClassifier model = RidgeClassifier(random_state=18) return model def get_features(data): def remove_trend(prices_pandas_): prices_pandas = prices_pandas_.copy(True) assets = prices_pandas.columns for asset in assets: prices_pandas[asset] = np.log(prices_pandas[asset]) return prices_pandas price = data.sel(field="close").ffill('time').bfill('time').fillna(0) # fill NaN for_result = price.to_pandas() features_no_trend_df = remove_trend(for_result) return features_no_trend_df def get_target_classes(data): price_current = data.sel(field="close").dropna('time') price_future = price_current.shift(time=-1).dropna('time') class_positive = 1 class_negative = 0 target_is_price_up = xr.where(price_future > price_current, class_positive, class_negative) return target_is_price_up.to_pandas() futures = market_data["futures"] crypto = market_data["crypto"] asset_name_all = futures.asset.values weights_df = futures.sel(field="close").isel(time=-1).to_pandas() for asset_name in asset_name_all: features_data = xr.concat([crypto, futures.sel(asset=[asset_name])], dim='asset') features_all_df = get_features(features_data) target_all_df = get_target_classes(futures.sel(asset=[asset_name])) target_for_learn_df = target_all_df[asset_name] feature_for_learn_df = features_all_df[:-1] # last value reserved for prediction # align features and targets target_for_learn_df, feature_for_learn_df = target_for_learn_df.align(feature_for_learn_df, axis=0, join='inner') model = get_ml_model() try: model.fit(feature_for_learn_df.values, target_for_learn_df) feature_for_predict_df = features_all_df[-1:] predict = model.predict(feature_for_predict_df.values) weights_df[asset_name] = predict except: logging.exception("model failed") # if there is exception, return zero values return xr.zeros_like(crypto.isel(field=0, time=0)) output = weights_df.to_xarray() output = output.drop(['time','field'], errors='ignore') return output def ta_strategy(market_data): close = market_data["futures"].sel(field='close') roc = qnta.roc(close, 20) output = xr.where(roc > 0, 1, 0).isel(time=-1) output = output.drop(['time','field'], errors='ignore') return output def hybrid_strategy(data): # try: # return predict_weights(data) # except: # return ta_strategy(data) if data['futures'].time[-1] >= pd.to_datetime('2014-01-01'): return predict_weights(data) else: return ta_strategy(data) weights = qnbt.backtest( competition_type="futures", load_data=load_data, lookback_period=60, start_date='2006-01-01', strategy=hybrid_strategy, window=build_data_for_one_step, analyze=True, build_plots=True )
-