def construct_backtest(ticker, vendor_ticker, sma_period, data_source, start_date, quandl_api_key): backtest = Backtest() br = BacktestRequest() # Set all the parameters for the backtest br.start_date = start_date br.finish_date = datetime.datetime.utcnow() br.spot_tc_bp = 2.5 # 2.5 bps bid/ask spread br.ann_factor = 252 tech_params = TechParams() tech_params.sma_period = sma_period indicator = 'SMA' md_request = MarketDataRequest( start_date=start_date, finish_date=datetime.date.today(), freq='daily', data_source=data_source, tickers=ticker, fields=['close'], vendor_tickers=vendor_ticker, quandl_api_key=quandl_api_key) market = Market(market_data_generator=MarketDataGenerator()) # Download the market data (the asset we are trading is also # being used to generate the signal) asset_df = market.fetch_market(md_request) spot_df = asset_df # Use technical indicator to create signals # (we could obviously create whatever function we wanted for generating the signal dataframe) # However, finmarketpy has some technical indicators built in (and some signals too) tech_ind = TechIndicator() tech_ind.create_tech_ind(spot_df, indicator, tech_params); signal_df = tech_ind.get_signal() # use the same data for generating signals backtest.calculate_trading_PnL(br, asset_df, signal_df, None, False) # Get the returns and signals for the portfolio port = backtest.portfolio_cum() port.columns = [indicator + ' = ' + str(tech_params.sma_period) + ' ' + str(backtest.portfolio_pnl_desc()[0])] signals = backtest.portfolio_signal() # returns = backtest.pnl() return port, signals
def __init__(self): super(MarketDataRequest, self).__init__() self.logger = LoggerManager().getLogger(__name__) self.__signal_name = None # output parameters for backtest (should we add returns statistics on legends, write CSVs with returns etc.) self.__plot_start = None self.__calc_stats = True self.__write_csv = False self.__write_csv_pnl = False self.__plot_interim = False self.__include_benchmark = False self.__tech_params = TechParams() # default parameters for portfolio level vol adjustment self.__portfolio_vol_adjust = False self.__portfolio_vol_period_shift = 0 self.__portfolio_vol_rebalance_freq = None self.__portfolio_vol_resample_freq = None self.__portfolio_vol_resample_type = 'mean' self.__portfolio_vol_target = 0.1 # 10% vol target self.__portfolio_vol_max_leverage = None self.__portfolio_vol_periods = 20 self.__portfolio_vol_obs_in_year = 252 # default parameters for signal level vol adjustment self.__signal_vol_adjust = False self.__signal_vol_period_shift = 0 self.__signal_vol_rebalance_freq = None self.__signal_vol_resample_freq = None self.__signal_vol_resample_type = 'mean' self.__signal_vol_target = 0.1 # 10% vol target self.__signal_vol_max_leverage = None self.__signal_vol_periods = 20 self.__signal_vol_obs_in_year = 252 # portfolio notional size self.__portfolio_notional_size = None self.__portfolio_combination = None self.__portfolio_combination_weights = None # parameters for maximum position limits (expressed as whole portfolio) self.__max_net_exposure = None self.__max_abs_exposure = None self.__position_clip_rebalance_freq = None self.__position_clip_resample_freq = None # by default apply max position criterion on last business day of month self.__position_clip_resample_type = 'mean' self.__position_clip_period_shift = 0 # take profit and stop loss parameters self.__take_profit = None self.__stop_loss = None # should we delay the signal? self.__signal_delay = 0
def __init__(self): super(MarketDataRequest, self).__init__() self.__signal_name = None # output parameters for backtest (should we add returns statistics on legends, write CSVs with returns etc.) self.__plot_start = None self.__calc_stats = True self.__write_csv = False self.__write_csv_pnl = False self.__plot_interim = False self.__include_benchmark = False self.__tech_params = TechParams() # default parameters for portfolio level vol adjustment self.__portfolio_vol_adjust = False self.__portfolio_vol_period_shift = 0 self.__portfolio_vol_rebalance_freq = None self.__portfolio_vol_resample_freq = None self.__portfolio_vol_resample_type = 'mean' self.__portfolio_vol_target = 0.1 # 10% vol target self.__portfolio_vol_max_leverage = None self.__portfolio_vol_periods = 20 self.__portfolio_vol_obs_in_year = 252 # default parameters for signal level vol adjustment self.__signal_vol_adjust = False self.__signal_vol_period_shift = 0 self.__signal_vol_rebalance_freq = None self.__signal_vol_resample_freq = None self.__signal_vol_resample_type = 'mean' self.__signal_vol_target = 0.1 # 10% vol target self.__signal_vol_max_leverage = None self.__signal_vol_periods = 20 self.__signal_vol_obs_in_year = 252 # portfolio notional size self.__portfolio_notional_size = None self.__portfolio_combination = None self.__portfolio_combination_weights = None # parameters for maximum position limits (expressed as whole portfolio) self.__max_net_exposure = None self.__max_abs_exposure = None self.__position_clip_rebalance_freq = None self.__position_clip_resample_freq = None # by default apply max position criterion on last business day of month self.__position_clip_resample_type = 'mean' self.__position_clip_period_shift = 0 # take profit and stop loss parameters self.__take_profit = None self.__stop_loss = None # should we delay the signal? self.__signal_delay = 0 # annualization factor for return stats (and should we resample data first before calculating it?) self.__ann_factor = 252 self.__resample_ann_factor = None # how do we create a cumulative index of strategy returns # either multiplicative starting a 100 # or additive starting at 0 self.__cum_index = 'mult' # 'mult' or 'add'
def construct_strategy(self, br=None): """ construct_strategy - Constructs the returns for all the strategies which have been specified. - gets parameters form fill_backtest_request - market data from fill_assets """ calculations = Calculations() # get the parameters for backtesting if hasattr(self, 'br'): br = self.br elif br is None: br = self.load_parameters() # get market data for backtest asset_df, spot_df, spot_df2, basket_dict = self.load_assets() if hasattr(br, 'tech_params'): tech_params = br.tech_params else: tech_params = TechParams() cumresults = pandas.DataFrame(index=asset_df.index) portleverage = pandas.DataFrame(index=asset_df.index) from collections import OrderedDict ret_statsresults = OrderedDict() # each portfolio key calculate returns - can put parts of the portfolio in the key for key in basket_dict.keys(): asset_cut_df = asset_df[[x + '.close' for x in basket_dict[key]]] spot_cut_df = spot_df[[x + '.close' for x in basket_dict[key]]] self.logger.info("Calculating " + key) results, backtest = self.construct_individual_strategy( br, spot_cut_df, spot_df2, asset_cut_df, tech_params, key) cumresults[results.columns[0]] = results portleverage[results.columns[0]] = backtest.get_porfolio_leverage() ret_statsresults[key] = backtest.get_portfolio_pnl_ret_stats() # for a key, designated as the final strategy save that as the "strategy" if key == self.FINAL_STRATEGY: self._strategy_pnl = results self._strategy_pnl_ret_stats = backtest.get_portfolio_pnl_ret_stats( ) self._strategy_leverage = backtest.get_porfolio_leverage() self._strategy_signal = backtest.get_porfolio_signal() self._strategy_pnl_trades = backtest.get_pnl_trades() # get benchmark for comparison benchmark = self.construct_strategy_benchmark() cumresults_benchmark = self.compare_strategy_vs_benchmark( br, cumresults, benchmark) self._strategy_group_benchmark_ret_stats = ret_statsresults if hasattr(self, '_benchmark_ret_stats'): ret_statslist = ret_statsresults ret_statslist['Benchmark'] = (self._benchmark_ret_stats) self._strategy_group_benchmark_ret_stats = ret_statslist # calculate annualised returns years = calculations.average_by_annualised_year( calculations.calculate_returns(cumresults_benchmark)) self._strategy_group_pnl = cumresults self._strategy_group_pnl_ret_stats = ret_statsresults self._strategy_group_benchmark_pnl = cumresults_benchmark self._strategy_group_leverage = portleverage self._strategy_group_benchmark_annualised_pnl = years
# get all asset data br.start_date = "02 Jan 1990" br.finish_date = datetime.datetime.utcnow() br.spot_tc_bp = 2.5 # 2.5 bps bid/ask spread br.ann_factor = 252 # have vol target for each signal br.signal_vol_adjust = True br.signal_vol_target = 0.05 br.signal_vol_max_leverage = 3 br.signal_vol_periods = 60 br.signal_vol_obs_in_year = 252 br.signal_vol_rebalance_freq = 'BM' br.signal_vol_resample_freq = None tech_params = TechParams(); tech_params.sma_period = 200; indicator = 'SMA' # pick USD crosses in G10 FX # note: we are calculating returns from spot (it is much better to use to total return # indices for FX, which include carry) logger.info("Loading asset data...") tickers = ['EURUSD', 'USDJPY', 'GBPUSD', 'AUDUSD', 'USDCAD', 'NZDUSD', 'USDCHF', 'USDNOK', 'USDSEK'] vendor_tickers = ['FRED/DEXUSEU', 'FRED/DEXJPUS', 'FRED/DEXUSUK', 'FRED/DEXUSAL', 'FRED/DEXCAUS', 'FRED/DEXUSNZ', 'FRED/DEXSZUS', 'FRED/DEXNOUS', 'FRED/DEXSDUS'] md_request = MarketDataRequest( start_date = "01 Jan 1989", # start date finish_date = datetime.date.today(), # finish date
# get all asset data br.start_date = "02 Jan 1990" br.finish_date = datetime.datetime.utcnow() br.spot_tc_bp = 2.5 # 2.5 bps bid/ask spread br.ann_factor = 252 # have vol target for each signal br.signal_vol_adjust = True br.signal_vol_target = 0.05 br.signal_vol_max_leverage = 3 br.signal_vol_periods = 60 br.signal_vol_obs_in_year = 252 br.signal_vol_rebalance_freq = 'BM' br.signal_vol_resample_freq = None tech_params = TechParams() tech_params.sma_period = 200 indicator = 'SMA' # pick USD crosses in G10 FX # note: we are calculating returns from spot (it is much better to use to total return # indices for FX, which include carry) logger.info("Loading asset data...") tickers = [ 'EURUSD', 'USDJPY', 'GBPUSD', 'AUDUSD', 'USDCAD', 'NZDUSD', 'USDCHF', 'USDNOK', 'USDSEK' ] vendor_tickers = [ 'FRED/DEXUSEU', 'FRED/DEXJPUS', 'FRED/DEXUSUK', 'FRED/DEXUSAL',
def __init__(self): super(MarketDataRequest, self).__init__() self.logger = LoggerManager().getLogger(__name__) self.__signal_name = None self.__tech_params = TechParams()
from finmarketpy.economics import TechIndicator, TechParams from findatapy.util.loggermanager import LoggerManager logger = LoggerManager().getLogger(__name__) chart = Chart(engine='bokeh') tech_ind = TechIndicator() ###### Simple example loading local data and using finmarketpy engine # Load data from local file df = pd.read_csv("/Volumes/Data/s&p500.csv", index_col=0, parse_dates=['Date'], date_parser=lambda x: pd.datetime.strptime(x, '%Y-%m-%d')) # Calculate Volume Weighted Average Price (VWAP) tech_params = TechParams() tech_ind.create_tech_ind(df, 'VWAP', tech_params) df = tech_ind.get_techind() print(df) style = Style() style.title = 'S&P500 VWAP' style.scale_factor = 2 df = tech_ind.get_techind() chart.plot(df, style=style)
if run_example == 1 or run_example == 0: # Downloaded S&P500 md_request = MarketDataRequest( start_date="01 Jan 2000", # start date data_source='quandl', # use Quandl as data source tickers=['S&P500'], fields=['close', 'open', 'high', 'low'], # which fields to download vendor_tickers=['YAHOO/INDEX_GSPC'], # ticker (Bloomberg) vendor_fields=['close', 'open', 'high', 'low'], # which Bloomberg fields to download cache_algo='internet_load_return') # how to return data df = market.fetch_market(md_request) print(df) tech_params = TechParams() tech_params.atr_period = 14 tech_ind.create_tech_ind(df, 'ATR', tech_params) style = Style() style.title = 'S&P500 ATR' style.scale_factor = 2 style.file_output = "sp500.png" style.source = 'Quandl/Yahoo' df = tech_ind.get_techind() chart.plot(df, style=style)
###### fetch data from Quandl for BoE rate (using Bloomberg data) if run_example == 1 or run_example == 0: # downloaded S&P500 md_request = MarketDataRequest( start_date = "01 Jan 2000", # start date data_source = 'quandl', # use Quandl as data source tickers = ['S&P500'], fields = ['close', 'open', 'high', 'low'], # which fields to download vendor_tickers = ['YAHOO/INDEX_GSPC'], # ticker (Bloomberg) vendor_fields = ['close', 'open', 'high', 'low'], # which Bloomberg fields to download cache_algo = 'internet_load_return') # how to return data df = market.fetch_market(md_request) print(df) tech_params = TechParams() tech_params.atr_period = 14 tech_ind.create_tech_ind(df, 'ATR', tech_params) style = Style() style.title = 'S&P500 ATR' style.scale_factor = 2 style.file_output = "sp500.png" style.source = 'Quandl/Yahoo' df = tech_ind.get_techind() chart.plot(df, style=style)