plotguy 2.3.1__tar.gz → 2.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotguy
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: Plotguy
5
5
  Home-page: https://pypi.org/project/plotguy/
6
6
  Author: Plotguy Team
@@ -0,0 +1 @@
1
+ from .Database import *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotguy
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: Plotguy
5
5
  Home-page: https://pypi.org/project/plotguy/
6
6
  Author: Plotguy Team
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="plotguy",
8
- version="2.3.1",
8
+ version="2.3.2",
9
9
  author="Plotguy Team",
10
10
  author_email="plotguy.info@gmail.com",
11
11
  description="Plotguy",
@@ -1,563 +0,0 @@
1
- import warnings
2
- warnings.simplefilter("ignore", UserWarning)
3
- #warnings.simplefilter("ignore", RuntimeWarning)
4
-
5
- import datetime
6
- import os
7
- import sys
8
- import copy
9
- import multiprocessing as mp
10
- import time
11
- import zlib
12
- import requests
13
- import pandas as pd
14
- import numpy as np
15
- import io
16
- import re
17
-
18
- from .equity_curves import *
19
- from .signals import *
20
- from .aggregate import *
21
- from .components import *
22
- import itertools
23
- from bs4 import BeautifulSoup
24
-
25
- def get_all_para_combination(para_dict, backtest_attribute, df_dict, sec_profile, manager_list, count_down=False):
26
-
27
- key_to_keep = ['start_date',
28
- 'end_date',
29
- 'freq',
30
- 'market',
31
- 'sectype',
32
- 'initial_capital',
33
- 'data_folder',
34
- 'equity_curve_folder',
35
- 'secondary_data_folder',
36
- 'backtest_name',
37
- 'default_market_price',
38
- 'summary_mode']
39
-
40
- for k in backtest_attribute.copy().keys():
41
- if k not in key_to_keep:
42
- del backtest_attribute[k]
43
-
44
-
45
- risk_free_rate = get_risk_free_rate(backtest_attribute['start_date'], backtest_attribute['end_date'])
46
-
47
- freq = backtest_attribute['freq']
48
-
49
- intraday = True if freq != '1D' else False
50
- if intraday:
51
- if not 'summary_mode' in backtest_attribute:
52
- backtest_attribute['summary_mode'] = True
53
- backtest_attribute['intraday'] = True
54
- else:
55
- backtest_attribute['summary_mode'] = False
56
- backtest_attribute['intraday'] = False
57
-
58
- backtest_attribute['risk_free_rate'] = risk_free_rate
59
-
60
- para_keys = para_dict.keys()
61
- para_values = para_dict.values()
62
- para_list = list(itertools.product(*para_values))
63
- para_keys_str = '|'.join(para_keys)
64
-
65
- print('number of combination:', len(para_list))
66
-
67
- all_combinations = list(itertools.product(*para_values))
68
- all_para_combination = {}
69
-
70
- for combination in all_combinations:
71
- para_combination = dict(zip(para_keys, combination))
72
- para_combination.update(backtest_attribute)
73
- para_combination['manager_list'] = manager_list
74
-
75
- concatenated_values = ''.join(map(str, para_combination.values())).encode('utf-8')
76
- ref_code = zlib.crc32(concatenated_values)
77
-
78
- code = para_combination['code']
79
- para_combination['df'] = df_dict[code]
80
- para_combination['sec_profile'] = sec_profile
81
- para_combination['para_keys_str'] = para_keys_str
82
-
83
- all_para_combination[ref_code] = para_combination
84
-
85
- if count_down:
86
- print('5 second countdown before running backtest()')
87
- for i in range(5):
88
- print(5 - i)
89
- time.sleep(1)
90
- print(0)
91
-
92
- print(datetime.datetime.now().strftime('%H:%M:%S'), 'start running backtest()')
93
-
94
- return all_para_combination
95
-
96
- def generate_or_read_backtest_result(read_only, mp_mode, number_of_core, manager_list
97
- ,all_para_combination, backtest):
98
-
99
- if read_only and os.path.isfile('backtest_result.parquet'):
100
- backtest_result_df = pd.read_parquet('backtest_result.parquet')
101
- else:
102
- t1 = datetime.datetime.now()
103
- if mp_mode:
104
- pool = mp.Pool(processes=number_of_core)
105
- pool.map(backtest, all_para_combination.items())
106
- pool.close()
107
- else:
108
- for para_combination_item in all_para_combination.items():
109
- backtest(para_combination_item)
110
-
111
- backtest_result_df = pd.DataFrame(list(manager_list))
112
- backtest_result_df = backtest_result_df.set_index('ref_code')
113
-
114
- if os.path.isfile('backtest_result.parquet'):
115
- old_backtest_result_df = pd.read_parquet('backtest_result.parquet')
116
- backtest_result_df = pd.concat([backtest_result_df, old_backtest_result_df])
117
- backtest_result_df = backtest_result_df[~backtest_result_df.index.duplicated(keep='last')]
118
-
119
- backtest_result_df.to_parquet('backtest_result.parquet')
120
-
121
- print('backtest time used:', (datetime.datetime.now() - t1).seconds, 'seconds')
122
-
123
- backtest_result_df = backtest_result_df[backtest_result_df.index.isin(all_para_combination.keys())]
124
-
125
- return backtest_result_df
126
-
127
- def get_source_data_path(data_folder, code, freq):
128
- file_path = os.path.join(data_folder, code + '_' + freq + '.parquet')
129
- return file_path
130
-
131
-
132
- def save_backtest_result(df, para_combination_item):
133
-
134
- ref_code, para_combination = para_combination_item
135
-
136
- equity_curve_folder = para_combination['equity_curve_folder']
137
- manager_list = para_combination['manager_list']
138
- risk_free_rate = para_combination['risk_free_rate']
139
- default_market_price = para_combination['default_market_price']
140
- intraday = para_combination['intraday']
141
- long_short = para_combination['long_short']
142
-
143
- total_commission = df['commission'].sum()
144
-
145
- df = df[[default_market_price, 'action', 'trd_side', 'equity_value']]
146
- df = df.rename(columns={default_market_price: 'price'})
147
-
148
- eqiuty_curve_save_path = os.path.join('', equity_curve_folder, f'{ref_code}.parquet')
149
- ##############################################################
150
-
151
- if default_market_price == 'close':
152
- agg_price = 'last'
153
- elif default_market_price == 'open':
154
- agg_price = 'first'
155
- ### for intraday ###
156
- if intraday:
157
- df_daily = df.resample('D').agg({'price': agg_price})
158
- #df_daily = df.resample('D').agg({'price': agg_price, 'equity_value': agg_price})
159
- df_daily = df_daily[df_daily['price'].notna()]
160
- else:
161
- df_daily = df
162
-
163
- ########### price result ###############
164
- df_daily['running_max'] = df_daily['price'].cummax()
165
- df_daily['dd_dollar'] = df_daily['running_max'] - df_daily['price']
166
- df_daily['dd_pct'] = df_daily['dd_dollar'] / df_daily['running_max'] * 100
167
- price_mdd_dollar = df_daily['dd_dollar'].max()
168
- price_mdd_pct = df_daily['dd_pct'].max()
169
-
170
- price_pct_series = df_daily['price'].pct_change().dropna()
171
- price_net_profit = df_daily.at[df_daily.index[-1], 'price'] - df_daily.at[df_daily.index[0], 'price']
172
- holding_period_day = (df_daily.index[-1].date() - df_daily.index[0].date()).days
173
-
174
- price_return_on_capital = price_net_profit / df_daily.at[df_daily.index[0], 'price']
175
- price_annualized_return = (np.sign(1 + price_return_on_capital) * np.abs(1 + price_return_on_capital)) ** (
176
- 365 / holding_period_day) - 1
177
- price_annualized_std = price_pct_series.std() * math.sqrt(365)
178
- price_annualized_sr = (
179
- price_annualized_return - risk_free_rate / 100) / price_annualized_std if price_annualized_std != 0 else 0
180
- price_net_profit_to_mdd = price_net_profit / price_mdd_dollar if price_mdd_dollar != 0 else 0
181
-
182
- price_return_on_capital = round(100 * price_return_on_capital, 2)
183
- price_annualized_return = round(100 * price_annualized_return, 2)
184
- price_annualized_std = round(100 * price_annualized_std, 2)
185
- price_annualized_sr = round(price_annualized_sr, 2)
186
- price_net_profit_to_mdd = round(100 * price_net_profit_to_mdd, 2)
187
-
188
- last_action = df['action'].iloc[-1]
189
- if last_action == 'open':
190
- df = df.drop(df.index[-1])
191
- df_count = df[(df['trd_side'] == 'BUY') | (df['trd_side'] == 'SELL_SHORT')].copy()
192
-
193
- if len(df_count) == 0:
194
- num_of_trade = 0
195
- equity_net_profit = 0
196
- equity_return_on_capital = 0
197
- equity_annualized_return = 0
198
- equity_annualized_std = 0
199
- equity_annualized_sr = 0
200
- equity_net_profit_to_mdd = np.inf
201
- equity_mdd_dollar = 0
202
- equity_mdd_pct = 0
203
-
204
- num_of_win = 0
205
- num_of_trade = 0
206
- win_rate = 0
207
- yearly_stats_string = ''
208
-
209
- cov_return = 0
210
- cov_count = 0
211
- total_commission = 0
212
-
213
- start_year = df.index[0].year
214
- end_year = df.index[-1].year
215
-
216
- yearly_stats_string = ''
217
- for year in range(start_year, end_year + 1):
218
- yearly_stats_string += f'{year},year_trade_count:0.00,year_win_rate:00.00,year_return:-00.00|'
219
-
220
- yearly_stats_string = yearly_stats_string[:-1]
221
- correlation = 0
222
-
223
- elif len(df_count) > 0:
224
-
225
- ########### by year count, win rate and return ###############
226
- start_year = df.index[0].year
227
- end_year = df.index[-1].year
228
-
229
- num_of_trade = len(df_count)
230
- df_count = pd.concat([df_count, df[df['trd_side'] != ''].tail(1)])
231
- df_count['realized_pnl'] = df_count['equity_value'] - df_count['equity_value'].shift(1)
232
- df_count['win_trade'] = df_count['realized_pnl'] >= 0
233
-
234
- num_of_win = df_count['win_trade'].sum()
235
- win_rate = round(100 * num_of_win / num_of_trade, 2)
236
-
237
- yearly_stats = df_count.groupby(df_count.index.year).agg(
238
- year_pnl=('realized_pnl', 'sum'),
239
- year_win_count=('win_trade', 'sum'),
240
- year_trade_count=('realized_pnl', 'count'),
241
- year_start_equity_value=('equity_value', 'first'))
242
- yearly_stats['year_return'] = 100 * (yearly_stats['year_pnl'] / yearly_stats['year_start_equity_value'])
243
- yearly_stats['year_win_rate'] = 100 * (yearly_stats['year_win_count'] / yearly_stats['year_trade_count'])
244
-
245
- all_years = range(start_year, end_year + 1)
246
- current_years = yearly_stats.index
247
- missing_years = [year for year in all_years if year not in current_years]
248
-
249
- #if year_start_equity_value = df.at[df.index[0], 'equity_value'
250
- missing_rows = pd.DataFrame(
251
- { "year_pnl": 0,
252
- "year_win_count": 0,
253
- "year_trade_count": 0,
254
- "year_start_equity_value": 0,
255
- "year_return": 0,
256
- "year_win_rate": 0,
257
- }, index=missing_years)
258
- missing_rows.index.name = "datetime"
259
-
260
- yearly_stats = pd.concat([yearly_stats, missing_rows]).sort_index()
261
-
262
- cov_return = yearly_stats['year_return'].std() / yearly_stats['year_return'].mean() if yearly_stats['year_return'].mean() != 0 else 0
263
- cov_count = yearly_stats['year_trade_count'].std() / yearly_stats['year_trade_count'].mean() if yearly_stats['year_trade_count'].mean() != 0 else 0
264
-
265
- yearly_stats = yearly_stats.applymap(lambda x: f'{x:.2f}')
266
- formatted_rows = yearly_stats.apply(
267
- lambda
268
- row: f"{row.name},{'year_trade_count'}:{row['year_trade_count']},{'year_win_rate'}:{row['year_win_rate']},{'year_return'}:{row['year_return']}",
269
- axis=1)
270
-
271
- yearly_stats_string = "|".join(formatted_rows)
272
-
273
- ######## resample to daily #############
274
- if 'summary_mode' in para_combination:
275
- if para_combination['summary_mode']:
276
- eqiuty_curve_non_summary_save_path = os.path.join('', equity_curve_folder, f'{ref_code}_non-summary-intraday.parquet')
277
- df.to_parquet(eqiuty_curve_non_summary_save_path)
278
-
279
- ########### equity value result ###############
280
-
281
- ### for intraday ###
282
- if intraday:
283
- df = df_count.resample('D').agg({'equity_value': 'last'})
284
- df = pd.concat([df_daily, df], axis=1)
285
- df = df[df['price'].notna()]
286
- df['equity_value'] = df['equity_value'].ffill()
287
- df['equity_value'] = df['equity_value'].bfill()
288
-
289
- df['equity_value'] = df['equity_value'].astype(np.int32)
290
- ######################
291
-
292
- df['running_max'] = df['equity_value'].cummax()
293
- df['dd_dollar'] = df['running_max'] - df['equity_value']
294
- df['dd_pct'] = df['dd_dollar'] / df['running_max'] * 100
295
- equity_mdd_dollar = df['dd_dollar'].max()
296
- equity_mdd_pct = df['dd_pct'].max()
297
-
298
- holding_period_day = (df.index[-1].date() - df.index[0].date()).days
299
- equity_pct_series = df['equity_value'].pct_change().dropna()
300
- equity_net_profit = df.at[df.index[-1], 'equity_value'] - df.at[df.index[0], 'equity_value']
301
-
302
- equity_return_on_capital = equity_net_profit / df.at[df.index[0], 'equity_value']
303
- if 1 + equity_return_on_capital > 0:
304
- equity_annualized_return = (np.sign(1 + equity_return_on_capital) * np.abs(1 + equity_return_on_capital)) ** (365 / holding_period_day) - 1
305
- else:
306
- equity_annualized_return = -1
307
-
308
- equity_annualized_std = equity_pct_series.std() * math.sqrt(365)
309
- equity_annualized_sr = (
310
- equity_annualized_return - risk_free_rate / 100) / equity_annualized_std if equity_annualized_std != 0 else 0
311
- equity_net_profit_to_mdd = equity_net_profit / equity_mdd_dollar if equity_mdd_dollar != 0 else 0
312
-
313
- equity_return_on_capital = round(100 * equity_return_on_capital, 2)
314
- equity_annualized_return = round(100 * equity_annualized_return, 2)
315
- equity_annualized_std = round(100 * equity_annualized_std, 2)
316
- equity_annualized_sr = round(equity_annualized_sr, 2)
317
- equity_net_profit_to_mdd = round(100 * equity_net_profit_to_mdd, 2)
318
-
319
- df['equity_return'] = df['equity_value'].pct_change() * 100
320
- df['price_return'] = df['price'].pct_change() * 100
321
-
322
- correlation = df['equity_return'].corr(df['price_return'])
323
-
324
- if long_short == 'short':
325
- return_on_capital_diff = equity_annualized_return - (-1) * price_annualized_return
326
- correlation *= -1
327
- else:
328
- ### consider both long and long_short ###
329
- return_on_capital_diff = equity_annualized_return - price_annualized_return
330
-
331
- if intraday:
332
- df = df[['price', 'equity_value']]
333
- elif not intraday:
334
- df = df[['price', 'action', 'trd_side', 'equity_value']]
335
- df.to_parquet(eqiuty_curve_save_path)
336
- print('backtest is runnung...', eqiuty_curve_save_path)
337
-
338
- ####################################
339
- del para_combination['df']
340
- del para_combination['sec_profile']
341
- del para_combination['manager_list']
342
-
343
- cov_return = round(cov_return, 2)
344
- cov_count = round(cov_count, 2)
345
- total_commission = int(round(total_commission))
346
- correlation = round(correlation, 3)
347
-
348
- backtest_result_dict = {
349
- 'ref_code': ref_code,
350
- 'num_of_trade': num_of_trade,
351
-
352
- 'equity_net_profit': equity_net_profit,
353
- 'equity_return_on_capital': equity_return_on_capital,
354
- 'equity_annualized_return': equity_annualized_return,
355
- 'equity_annualized_std': equity_annualized_std,
356
- 'equity_annualized_sr': equity_annualized_sr,
357
- 'equity_net_profit_to_mdd': equity_net_profit_to_mdd,
358
- 'equity_mdd_dollar': equity_mdd_dollar,
359
- 'equity_mdd_pct': equity_mdd_pct,
360
-
361
- 'price_net_profit' : price_net_profit,
362
- 'price_return_on_capital': price_return_on_capital,
363
- 'price_annualized_return': price_annualized_return,
364
- 'price_annualized_std': price_annualized_std,
365
- 'price_annualized_sr': price_annualized_sr,
366
- 'price_net_profit_to_mdd': price_net_profit_to_mdd,
367
- 'price_mdd_dollar': price_mdd_dollar,
368
- 'price_mdd_pct': price_mdd_pct,
369
-
370
- 'return_on_capital_diff': return_on_capital_diff,
371
-
372
- 'num_of_win': num_of_win,
373
- 'num_of_trade': num_of_trade,
374
- 'win_rate': win_rate,
375
- 'yearly_stats_string': yearly_stats_string,
376
- 'cov_return': cov_return,
377
- 'cov_count': cov_count,
378
- 'correlation': correlation,
379
- 'total_commission': total_commission
380
- }
381
-
382
- para_combination.update(backtest_result_dict)
383
- manager_list.append(para_combination)
384
-
385
-
386
- ########################################################################################################
387
- ########################################################################################################
388
- ########################################################################################################
389
-
390
- def get_risk_free_rate(start_date, end_date):
391
-
392
- if '-' in start_date:
393
- start_date_year = datetime.datetime.strptime(start_date, '%Y-%m-%d').year
394
- end_date_year = datetime.datetime.strptime(end_date, '%Y-%m-%d').year
395
- else:
396
- start_date_year = datetime.datetime.strptime(start_date, '%Y%m%d').year
397
- end_date_year = datetime.datetime.strptime(end_date, '%Y%m%d').year
398
-
399
- try:
400
- if end_date_year == start_date_year and end_date_year == datetime.datetime.now().year:
401
- risk_free_rate = get_latest_fed_fund_rate()
402
- else:
403
- risk_free_rate = get_geometric_mean_of_yearly_rate(start_date_year, end_date_year)
404
- except:
405
- try:
406
- risk_free_rate = get_geometric_mean_of_yearly_rate_backup(start_date_year, end_date_year)
407
- except:
408
- risk_free_rate = 2 # if network error, set rate to 2 %
409
- print('Network error. Risk free rate: {:.2f} %'.format(risk_free_rate))
410
-
411
- return risk_free_rate
412
-
413
-
414
- # def plot_signal_analysis(py_filename, output_folder, start_date, end_date, para_dict, signal_settings):
415
- # app = signals.Signals(py_filename, output_folder, start_date, end_date, para_dict, generate_backtest_output_path,
416
- # signal_settings)
417
- #
418
- # return app
419
-
420
-
421
- def plot(mode, backtest_result_df = None, number_of_curves=20, filter_list= []):
422
-
423
- if mode == 'equity_curves':
424
- if len(filter_list) > 0: filter_list = convert_filter_list(filter_list)
425
- app = equity_curves.Plot(backtest_result_df, number_of_curves, filter_list)
426
-
427
- if mode == 'aggregate':
428
- app = aggregate.Aggregate()
429
-
430
- return app
431
-
432
- def convert_filter_list(filter_list):
433
- '''
434
- filter string as follows
435
- equity_return_on_capital eg: 50% --> 50
436
- equity_annualized_return eg: 50% --> 50
437
- return_on_capital_diff eg: 50% --> 50
438
- equity_annualized_sr eg: 0.9
439
- equity_mdd_pct eg: 50% --> 50
440
- num_of_trade eg: 10
441
- cov_count eg: 1
442
- cov_return eg: 1
443
- correlation eg: 0.5
444
- win_rate eg: 50% --> 50
445
- '''
446
-
447
- for i in range(len(filter_list)):
448
- filter = filter_list[i]
449
- pattern = r'([a-zA-Z_]+)([<>=]+)(-?\d+\.?\d*)'
450
- match = re.match(pattern, filter)
451
-
452
- filter_list[i] = [match.group(1), match.group(2), match.group(3)]
453
-
454
- return filter_list
455
-
456
- def get_latest_fed_fund_rate():
457
- url = "https://fred.stlouisfed.org/series/FEDFUNDS"
458
- page = requests.get(url)
459
- soup = BeautifulSoup(page.content, "html.parser")
460
-
461
- fed_funds_rate = soup.find("span", class_="series-meta-observation-value").text
462
- print("Latest Federal Funds Rate:", fed_funds_rate, '%')
463
- # fed_funds_rate = float(fed_funds_rate) / 100
464
- fed_funds_rate = round(float(fed_funds_rate), 2)
465
- return fed_funds_rate
466
-
467
-
468
- def get_geometric_mean_of_yearly_rate(start_year, end_year):
469
- url = "https://fred.stlouisfed.org/graph/fredgraph.csv?id=DTB3"
470
- response = requests.get(url, timeout=10)
471
- data = response.text.split("\n")[:-1]
472
- data = [row.split(",") for row in data]
473
- df = pd.DataFrame(data[1:], columns=data[0])
474
- df.columns = ["date", "risk_free_rate"]
475
- df["date"] = pd.to_datetime(df["date"])
476
- df["risk_free_rate"] = pd.to_numeric(df["risk_free_rate"], errors='coerce')
477
- df.dropna(subset=['risk_free_rate'], inplace=True)
478
- print('Got Federal Funds Rate from stlouisfed.org')
479
-
480
- risk_free_rate_history_yearly = df.resample("A", on="date").mean()
481
- risk_free_rate_history_yearly = risk_free_rate_history_yearly.round(3)
482
-
483
- # show only start between start_year and end_year
484
- risk_free_rate_history_yearly = risk_free_rate_history_yearly[
485
- risk_free_rate_history_yearly.index.year >= start_year]
486
- risk_free_rate_history_yearly = risk_free_rate_history_yearly[risk_free_rate_history_yearly.index.year <= end_year]
487
-
488
- fed_fund_rate_geometric_mean = np.exp(np.log(risk_free_rate_history_yearly["risk_free_rate"]).mean())
489
- fed_fund_rate_geometric_mean = round(fed_fund_rate_geometric_mean, 2)
490
- print("Federal Funds Rate Geometric mean from {} to {}: {} %".format(start_year, end_year,
491
- fed_fund_rate_geometric_mean))
492
-
493
- return fed_fund_rate_geometric_mean
494
-
495
- def get_geometric_mean_of_yearly_rate_backup(start_year, end_year):
496
- url = '/get_fred'
497
- my_headers = {'token': '3f52e8c4-8c49-4c9a-8c57-1e4e9f6b0a40'}
498
- my_main_url = "http://120.26.40.125:8080"
499
- response = requests.get(f'{my_main_url}{url}', headers=my_headers)
500
- data_str = response.content.decode('utf-8')
501
- data_io = io.StringIO(data_str)
502
- df = pd.read_csv(data_io)
503
- df = df.rename(columns={'value' : 'risk_free_rate'})
504
- df["date"] = pd.to_datetime(df["date"])
505
- df.dropna(subset=['risk_free_rate'], inplace=True)
506
- print('Got Federal Funds Rate from backup source')
507
-
508
- risk_free_rate_history_yearly = df.resample("A", on="date").mean()
509
- risk_free_rate_history_yearly = risk_free_rate_history_yearly.round(3)
510
-
511
- # show only start between start_year and end_year
512
- risk_free_rate_history_yearly = risk_free_rate_history_yearly[
513
- risk_free_rate_history_yearly.index.year >= start_year]
514
- risk_free_rate_history_yearly = risk_free_rate_history_yearly[risk_free_rate_history_yearly.index.year <= end_year]
515
-
516
- fed_fund_rate_geometric_mean = np.exp(np.log(risk_free_rate_history_yearly["risk_free_rate"]).mean())
517
- fed_fund_rate_geometric_mean = round(fed_fund_rate_geometric_mean, 2)
518
- print("Federal Funds Rate Geometric mean from {} to {}: {} %".format(start_year, end_year,
519
- fed_fund_rate_geometric_mean))
520
-
521
- return fed_fund_rate_geometric_mean
522
-
523
- def su_table_converter():
524
- all_str_dir = []
525
- for folder_name in os.listdir():
526
- if os.path.isfile(os.path.join(folder_name, 'saved_strategies.parquet')):
527
- all_str_dir.append(folder_name)
528
-
529
- su_dict = {'backtest_name': [], 'code': [], 'freq': [], 'para_items_str': [], 'initial_capital': [],
530
- 'equity_mdd_pct': []}
531
-
532
- for str_dir in all_str_dir:
533
- saved_strategies_path = os.path.join(str_dir, 'saved_strategies.parquet')
534
- saved_strategies_df = pd.read_parquet(saved_strategies_path)
535
- saved_strategies_df = saved_strategies_df.reset_index(drop=True)
536
-
537
- if len(saved_strategies_df.columns) > 1:
538
- for i, row in saved_strategies_df.iterrows():
539
- backtest_name = row['backtest_name']
540
- freq = row['freq']
541
- para_keys_str = row['para_keys_str']
542
- equity_mdd_pct = row['equity_mdd_pct']
543
- initial_capital = row['initial_capital']
544
-
545
- para_items_str = ''
546
- para_keys_str_list = para_keys_str.split('|')
547
- for para_key in para_keys_str_list:
548
- para_value = str(saved_strategies_df.at[i, para_key])
549
- if para_key == 'code':
550
- code = para_value
551
- else:
552
- para_items_str += para_key + '=' + para_value + '|'
553
- para_items_str = para_items_str[:-1]
554
-
555
- su_dict['backtest_name'].append(backtest_name)
556
- su_dict['code'].append(code)
557
- su_dict['freq'].append(freq)
558
- su_dict['para_items_str'].append(para_items_str)
559
- su_dict['equity_mdd_pct'].append(equity_mdd_pct)
560
- su_dict['initial_capital'].append(initial_capital)
561
-
562
- su_table = pd.DataFrame(su_dict)
563
- return su_table
File without changes
File without changes
File without changes
File without changes
File without changes