-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathanalysis.py
112 lines (102 loc) · 3.83 KB
/
analysis.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
# -*- coding: utf-8 -*-
# @Time : 9/9/2022 2:38 pm
# @Author : Joseph Chen
# @Email : [email protected]
# @FileName: analysis.py
"""
Copyright (C) 2020 Joseph Chen - All Rights Reserved
You may use, distribute and modify this code under the
terms of the JXW license, which unfortunately won't be
written for another century.
You should have received a copy of the JXW license with
this file. If not, please write to: [email protected]
"""
from datetime import datetime
import ast
# import pickle
# import matplotlib.pyplot as plt
import pandas as pd
from qtrader.plugins.analysis.metrics import sharpe_ratio
from qtrader.plugins.analysis.metrics import rolling_maximum_drawdown
instruments = {
"security": {
"Backtest": ["BTC.USD", "EOS.USD", "ETH.USD", "LTC.USD", "TRX.USD", "XRP.USD"],
},
"lot": {
"Backtest": [1, 1, 1, 1, 1, 1],
},
"commission": {
"Backtest": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
},
"slippage": {
"Backtest": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
}
}
# with open("saved_results/opt_params_5min.pkl", "rb") as f:
# opt_params = pickle.load(f)
# # select securities to trade
# opt_params = {k: v for k, v in opt_params.items() if v["best_loss"] < 0}
# print(opt_params)
# number_instruments = len(opt_params)
result_df = pd.read_csv(
"strategies/pairs_strategy/saved_results/60min_crypto/out_of_sample/result_pairs.csv")
# # Plot normalized prices
# closes_df = pd.DataFrame(
# index=result_df.datetime.apply(
# lambda x: datetime.strptime(
# ast.literal_eval(x)[0], "%Y-%m-%d %H:%M:%S")),
# # columns=instruments["security"]["Backtest"],
# columns=["TRX.USD", "XRP.USD", "BTC.USD"],
# )
# for i, sec_code in enumerate(closes_df.columns):
# closes_df[sec_code] = result_df.close.apply(
# lambda x: ast.literal_eval(x)[0][i]
# ).to_list()
#
# range_start = datetime(2021, 1, 29)
# range_end = datetime(2021, 2, 1)
# closes_df = closes_df[
# (closes_df.index >= range_start)
# & (closes_df.index <= range_end)
# ]
# norm_closes_df = closes_df/closes_df.iloc[0]
# norm_closes_df.plot()
# plt.show()
# print("-"*40)
# Calculate performance
perf_df = pd.DataFrame(
index=result_df.datetime.apply(
lambda x: datetime.strptime(
ast.literal_eval(x)[0], "%Y-%m-%d %H:%M:%S")),
columns=["portfolio_value"]
)
perf_df["portfolio_value"] = result_df.strategy_portfolio_value.apply(
lambda x: sum(ast.literal_eval(x))).to_list()
perf_daily_df = perf_df.resample('D').agg({"portfolio_value": "last"})
sr = sharpe_ratio(
returns=(perf_daily_df["portfolio_value"].diff()
/ perf_daily_df["portfolio_value"].iloc[0]).dropna(),
days=365
)
roll_mdd = rolling_maximum_drawdown(perf_daily_df['portfolio_value'])
number_instruments = 15 # number_instruments
number_of_trading_days = (
perf_daily_df.index[-1] - perf_daily_df.index[0]).days
num_trades = result_df.action.apply(lambda x: ast.literal_eval(x)[
0].count('OPEN')).sum() // 2
tot_return = (perf_daily_df["portfolio_value"].iloc[-1]
/ perf_daily_df["portfolio_value"].iloc[0]) - 1
annualizd_return = tot_return * 365 / number_of_trading_days
print(
"____________Performance____________\n"
+ "Start Date: {}\n".format(perf_daily_df.index[0].strftime("%Y-%m-%d"))
+ "End Date: {}\n".format(perf_daily_df.index[-1].strftime("%Y-%m-%d"))
+ "Number of Trading Days: {}\n".format(number_of_trading_days)
+ "Number of Instruments: {}\n".format(number_instruments)
+ "Number of Trades: {}\n".format(num_trades)
+ "Total Return: {:.2f}%\n".format(tot_return * 100)
+ "Annualized Return: {:.2f}%\n".format(annualizd_return * 100)
+ "Sharpe Ratio: {:.2f}\n".format(sr)
+ "Rolling Maximum Drawdown: {:.2f}%\n".format(roll_mdd.min() * 100)
)
print("Performance is done.")