-
-
Notifications
You must be signed in to change notification settings - Fork 490
/
tradingmodelfxtrend_example.py
243 lines (178 loc) · 9.08 KB
/
tradingmodelfxtrend_example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
__author__ = 'saeedamen'
#
# Copyright 2016 Cuemacro
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# See the License for the specific language governing permissions and limitations under the License.
#
"""
TradingModelFXCTA
Shows how to create a simple FX CTA style strategy, using the StrategyTemplate abstract class (backtest_examples.py
is a lower level way of doing this).
"""
import datetime
from findatapy.market import Market, MarketDataGenerator, MarketDataRequest
from finmarketpy.backtest import TradingModel, BacktestRequest
from finmarketpy.economics import TechIndicator
from chartpy import Style
class TradingModelFXTrend_Example(TradingModel):
def __init__(self):
super(TradingModel, self).__init__()
##### FILL IN WITH YOUR OWN PARAMETERS FOR display, dumping, TSF etc.
self.market = Market(market_data_generator=MarketDataGenerator())
self.DUMP_PATH = ''
self.FINAL_STRATEGY = 'FX trend'
self.SCALE_FACTOR = 1
self.DEFAULT_PLOT_ENGINE = 'matplotlib'
# self.CHART_STYLE = Style(plotly_plot_mode='offline_jupyter')
self.br = self.load_parameters()
return
###### Parameters and signal generations (need to be customised for every model)
def load_parameters(self, br = None):
if br is not None: return br
##### FILL IN WITH YOUR OWN BACKTESTING PARAMETERS
br = BacktestRequest()
# get all asset data
br.start_date = "04 Jan 1989"
br.finish_date = datetime.datetime.utcnow().date()
br.spot_tc_bp = 0.5
br.ann_factor = 252
br.plot_start = "01 Apr 2015"
br.calc_stats = True
br.write_csv = False
br.plot_interim = True
br.include_benchmark = True
# have vol target for each signal
br.signal_vol_adjust = True
br.signal_vol_target = 0.1
br.signal_vol_max_leverage = 5
br.signal_vol_periods = 20
br.signal_vol_obs_in_year = 252
br.signal_vol_rebalance_freq = 'BM'
br.signal_vol_resample_freq = None
# have vol target for portfolio
br.portfolio_vol_adjust = True
br.portfolio_vol_target = 0.1
br.portfolio_vol_max_leverage = 5
br.portfolio_vol_periods = 20
br.portfolio_vol_obs_in_year = 252
br.portfolio_vol_rebalance_freq = 'BM'
br.portfolio_vol_resample_freq = None
# tech params
br.tech_params.sma_period = 200
return br
def load_assets(self, br = None):
##### FILL IN WITH YOUR ASSET DATA
from findatapy.util.loggermanager import LoggerManager
logger = LoggerManager().getLogger(__name__)
# for FX basket
full_bkt = ['EURUSD', 'USDJPY', 'GBPUSD', 'AUDUSD', 'USDCAD',
'NZDUSD', 'USDCHF', 'USDNOK', 'USDSEK']
basket_dict = {}
for i in range(0, len(full_bkt)):
basket_dict[full_bkt[i]] = [full_bkt[i]]
basket_dict['FX trend'] = full_bkt
br = self.load_parameters(br = br)
logger.info("Loading asset data...")
vendor_tickers = ['FRED/DEXUSEU', 'FRED/DEXJPUS', 'FRED/DEXUSUK', 'FRED/DEXUSAL', 'FRED/DEXCAUS',
'FRED/DEXUSNZ', 'FRED/DEXSZUS', 'FRED/DEXNOUS', 'FRED/DEXSDUS']
market_data_request = MarketDataRequest(
start_date = br.start_date, # start date
finish_date = br.finish_date, # finish date
freq = 'daily', # daily data
data_source = 'quandl', # use Quandl as data source
tickers = full_bkt, # ticker (Thalesians)
fields = ['close'], # which fields to download
vendor_tickers = vendor_tickers, # ticker (Quandl)
vendor_fields = ['close'], # which Bloomberg fields to download
cache_algo = 'cache_algo_return') # how to return data
asset_df = self.market.fetch_market(market_data_request)
# if web connection fails read from CSV
if asset_df is None:
import pandas
asset_df = pandas.read_csv("d:/fxcta.csv", index_col=0, parse_dates=['Date'],
date_parser = lambda x: pandas.datetime.strptime(x, '%Y-%m-%d'))
# signalling variables
spot_df = asset_df
spot_df2 = None
# asset_df
return asset_df, spot_df, spot_df2, basket_dict
def construct_signal(self, spot_df, spot_df2, tech_params, br, run_in_parallel=False):
##### FILL IN WITH YOUR OWN SIGNALS
# use technical indicator to create signals
# (we could obviously create whatever function we wanted for generating the signal dataframe)
tech_ind = TechIndicator()
tech_ind.create_tech_ind(spot_df, 'SMA', tech_params);
signal_df = tech_ind.get_signal()
return signal_df
def construct_strategy_benchmark(self):
###### FILL IN WITH YOUR OWN BENCHMARK
tsr_indices = MarketDataRequest(
start_date = self.br.start_date, # start date
finish_date = self.br.finish_date, # finish date
freq = 'daily', # intraday data
data_source = 'quandl', # use Bloomberg as data source
tickers = ["EURUSD"], # tickers to download
vendor_tickers=['FRED/DEXUSEU'],
fields = ['close'], # which fields to download
vendor_fields = ['close'],
cache_algo = 'cache_algo_return') # how to return data)
df = self.market.fetch_market(tsr_indices)
df.columns = [x.split(".")[0] for x in df.columns]
return df
if __name__ == '__main__':
# just change "False" to "True" to run any of the below examples
# create a FX trend strategy then chart the returns, leverage over time
if True:
model = TradingModelFXTrend_Example()
model.construct_strategy()
model.plot_strategy_pnl() # plot the final strategy
model.plot_strategy_leverage() # plot the leverage of the portfolio
model.plot_strategy_group_pnl_trades() # plot the individual trade P&Ls
model.plot_strategy_group_benchmark_pnl() # plot all the cumulative P&Ls of each component
model.plot_strategy_group_benchmark_pnl_ir() # plot all the IR of individual components
model.plot_strategy_group_leverage() # plot all the individual leverages
from finmarketpy.backtest import TradeAnalysis
ta = TradeAnalysis()
# create statistics for the model returns using both finmarketpy and pyfolio
ta.run_strategy_returns_stats(model, engine='finmarketpy')
# ta.run_strategy_returns_stats(model, engine='pyfolio')
# model.plot_strategy_group_benchmark_annualised_pnl()
# create a FX CTA strategy, then examine how P&L changes with different vol targeting
# and later transaction costs
if True:
strategy = TradingModelFXTrend_Example()
from finmarketpy.backtest import TradeAnalysis
ta = TradeAnalysis()
ta.run_strategy_returns_stats(model, engine='finmarketpy')
# which backtesting parameters to change
# names of the portfolio
# broad type of parameter name
parameter_list = [
{'portfolio_vol_adjust': True, 'signal_vol_adjust' : True},
{'portfolio_vol_adjust': False, 'signal_vol_adjust' : False}]
pretty_portfolio_names = \
['Vol target',
'No vol target']
parameter_type = 'vol target'
ta.run_arbitrary_sensitivity(strategy,
parameter_list=parameter_list,
pretty_portfolio_names=pretty_portfolio_names,
parameter_type=parameter_type)
# now examine sensitivity to different transaction costs
tc = [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2.0]
ta.run_tc_shock(strategy, tc=tc)
# how does P&L change on day of month
ta.run_day_of_month_analysis(strategy)
# create a FX CTA strategy then use TradeAnalysis (via pyfolio) to analyse returns
if False:
from finmarketpy.backtest import TradeAnalysis
model = TradingModelFXTrend_Example()
model.construct_strategy()
tradeanalysis = TradeAnalysis()
tradeanalysis.run_strategy_returns_stats(strategy)