Skip to content

Commit 4ac17a3

Browse files
committed
Increased financepy version and file formatting
1 parent 5721e8c commit 4ac17a3

39 files changed

+1526
-924
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ Calculate event study around events for asset (see examples/events_examples.py)
6060
# Requirements
6161

6262
Major requirements
63-
* Required: Python 3.8
64-
* Required: pandas 1.2.3, numpy etc.
63+
* Required: Python 3.10
64+
* Required: pandas, numpy etc.
6565
* Required: findatapy for downloading market data (https://github.com/cuemacro/findatapy)
6666
* Required: chartpy for funky interactive plots (https://github.com/cuemacro/chartpy)
6767

@@ -187,6 +187,9 @@ In finmarketpy/examples you will find several examples, including some simple tr
187187

188188
# finmarketpy log
189189

190+
* 07 Mar 2025
191+
* Merge changes for pyproject.toml etc.
192+
* Formatting towards PEP8
190193
* 09 Nov 2024
191194
* Changed trend following example to use FRED
192195
* 19 May 2024

finmarketpy/backtest/backtestcomparison.py

+32-17
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
__author__ = 'saeedamen' # Saeed Amen
2+
13
#
24
# Copyright 2016-2020 Cuemacro - https://www.cuemacro.com / @cuemacro
35
#
4-
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
5-
# License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
7+
# use this file except in compliance with the License. You may obtain a copy of
8+
# the License at http://www.apache.org/licenses/LICENSE-2.0
69
#
7-
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
8-
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# Unless required by applicable law or agreed to in writing, software distributed
11+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
# CONDITIONS OF ANY KIND, either express or implied.
913
#
10-
# See the License for the specific language governing permissions and limitations under the License.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
1116
#
1217

13-
1418
import numpy as np
1519
import pandas as pd
1620
from finmarketpy.util.marketconstants import MarketConstants
@@ -20,8 +24,8 @@
2024
from finmarketpy.backtest.backtestengine import TradingModel
2125
from chartpy import Chart, Style, ChartConstants
2226

23-
class BacktestComparison(object):
2427

28+
class BacktestComparison(object):
2529
DEFAULT_PLOT_ENGINE = ChartConstants().chartfactory_default_engine
2630
SCALE_FACTOR = ChartConstants().chartfactory_scale_factor
2731
CHART_SOURCE = ChartConstants().chartfactory_source
@@ -34,16 +38,19 @@ def __init__(self, models, ref_index=0,
3438
:param models: iterable of TradingModel instances.
3539
:param ref_index: index of the reference model in the list (for difference).
3640
"""
37-
if hasattr(models, "__iter__") and all([isinstance(x, TradingModel) for x in models]):
41+
if hasattr(models, "__iter__") and all(
42+
[isinstance(x, TradingModel) for x in models]):
3843
self.models = models
3944
self.ref_index = ref_index
4045
else:
41-
raise AttributeError("Models need to be an iterable of TradingModel instances.")
46+
raise AttributeError(
47+
"Models need to be an iterable of TradingModel instances.")
4248

4349
self.labels = labels
4450

4551
def plot_pnl(self, diff=True, silent_plot=False, reduce_plot=True):
46-
style = self.models[self.ref_index]._create_style("", "Strategy PnL", reduce_plot=reduce_plot)
52+
style = self.models[self.ref_index]._create_style("", "Strategy PnL",
53+
reduce_plot=reduce_plot)
4754

4855
models = self.models
4956
ref = self.ref_index
@@ -57,14 +64,16 @@ def plot_pnl(self, diff=True, silent_plot=False, reduce_plot=True):
5764
if self.labels is not None:
5865
df.columns = self.labels
5966

60-
chart = Chart(df, engine=self.DEFAULT_PLOT_ENGINE, chart_type='line', style=style)
67+
chart = Chart(df, engine=self.DEFAULT_PLOT_ENGINE, chart_type='line',
68+
style=style)
6169
if not silent_plot:
6270
chart.plot()
6371

6472
return chart
6573

6674
def plot_sharpe(self, silent_plot=False, reduce_plot=True):
67-
style = self.models[self.ref_index]._create_style("", "Sharpe Curve", reduce_plot=reduce_plot)
75+
style = self.models[self.ref_index]._create_style("", "Sharpe Curve",
76+
reduce_plot=reduce_plot)
6877

6978
models = self.models
7079
ref = self.ref_index
@@ -76,18 +85,23 @@ def plot_sharpe(self, silent_plot=False, reduce_plot=True):
7685

7786
df = pd.concat(annualized_sharpe, axis=1)
7887

79-
chart = Chart(df, engine=self.DEFAULT_PLOT_ENGINE, chart_type='bar', style=style)
88+
chart = Chart(df, engine=self.DEFAULT_PLOT_ENGINE, chart_type='bar',
89+
style=style)
8090
if not silent_plot:
8191
chart.plot()
8292
return chart
8393

84-
def plot_strategy_trade_notional(self, diff=True, silent_plot=False, reduce_plot=True):
85-
style = self.models[self.ref_index]._create_style("", "Trades (Scaled by Notional)", reduce_plot=reduce_plot)
94+
def plot_strategy_trade_notional(self, diff=True, silent_plot=False,
95+
reduce_plot=True):
96+
style = self.models[self.ref_index]._create_style("",
97+
"Trades (Scaled by Notional)",
98+
reduce_plot=reduce_plot)
8699

87100
models = self.models
88101
ref = self.ref_index
89102

90-
strategy_trade_notional = [model._strategy_trade_notional for model in models]
103+
strategy_trade_notional = [model._strategy_trade_notional for model in
104+
models]
91105

92106
df = pd.concat(strategy_trade_notional, axis=1)
93107

@@ -96,7 +110,8 @@ def plot_strategy_trade_notional(self, diff=True, silent_plot=False, reduce_plot
96110
if self.labels is not None:
97111
df.columns = self.labels
98112

99-
chart = Chart(df, engine=self.DEFAULT_PLOT_ENGINE, chart_type='bar', style=style)
113+
chart = Chart(df, engine=self.DEFAULT_PLOT_ENGINE, chart_type='bar',
114+
style=style)
100115
if not silent_plot:
101116
chart.plot()
102117

finmarketpy/backtest/backtestengine.py

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
__author__ = 'saeedamen'
1+
__author__ = 'saeedamen' # Saeed Amen
22

33
#
4-
# Copyright 2016 Cuemacro
4+
# Copyright 2016-2020 Cuemacro - https://www.cuemacro.com / @cuemacro
55
#
6-
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
7-
# License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
7+
# use this file except in compliance with the License. You may obtain a copy of
8+
# the License at http://www.apache.org/licenses/LICENSE-2.0
89
#
9-
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
10-
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# Unless required by applicable law or agreed to in writing, software distributed
11+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
# CONDITIONS OF ANY KIND, either express or implied.
1113
#
12-
# See the License for the specific language governing permissions and limitations under the License.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
1316
#
14-
1517
import numpy as np
1618
import pandas as pd
1719

@@ -273,23 +275,23 @@ def calculate_trading_PnL(
273275
# weighting each signal separately)
274276
portfolio_signal_before_weighting = pd.DataFrame(
275277
data=(
276-
portfolio_signal_before_weighting.values * position_clip_adjustment_matrix),
278+
portfolio_signal_before_weighting.values * position_clip_adjustment_matrix),
277279
index=portfolio_signal_before_weighting.index,
278280
columns=portfolio_signal_before_weighting.columns)
279281

280282
# Recalculate portfolio signal after adjustment (for portfolio
281283
# level positions)
282284
portfolio_signal = pd.DataFrame(
283285
data=(
284-
portfolio_signal.values * position_clip_adjustment_matrix),
286+
portfolio_signal.values * position_clip_adjustment_matrix),
285287
index=portfolio_signal.index,
286288
columns=portfolio_signal.columns)
287289

288290
# Recalculate portfolio leverage with position constraint
289291
# (multiply vectors elementwise)
290292
portfolio_leverage_df = pd.DataFrame(
291293
data=(
292-
portfolio_leverage_df.values * position_clip_adjustment.values),
294+
portfolio_leverage_df.values * position_clip_adjustment.values),
293295
index=portfolio_leverage_df.index,
294296
columns=portfolio_leverage_df.columns)
295297

@@ -1037,7 +1039,8 @@ def load_model(path):
10371039
return pkl
10381040

10391041
####### Generic functions for every backtest
1040-
def construct_strategy(self, br: BacktestRequest = None, run_in_parallel: bool = False) -> pd.DataFrame:
1042+
def construct_strategy(self, br: BacktestRequest = None,
1043+
run_in_parallel: bool = False) -> pd.DataFrame:
10411044
"""Constructs the returns for all the strategies which have been specified.
10421045
10431046
It gets backtesting parameters from fill_backtest_request (although
@@ -2479,7 +2482,7 @@ def _create_style(self, title, file_add, reduce_plot=True):
24792482
style.height = self.HEIGHT
24802483
style.source = self.CHART_SOURCE
24812484
style.silent_display = not (self.SHOW_CHARTS)
2482-
style.plotly_plot_mode = self.PLOTLY_PLOT_MODE # Smaller file sizes
2485+
style.plotly_plot_mode = self.PLOTLY_PLOT_MODE # Smaller file sizes
24832486

24842487
style.legend_bgcolor = 'rgba(0,0,0,0)'
24852488

@@ -2521,8 +2524,8 @@ def optimize_portfolio_weights(
25212524
signal_df: pd.DataFrame,
25222525
signal_pnl_cols: List[str],
25232526
br: BacktestRequest = None) -> (
2524-
pd.DataFrame, pd.DataFrame, pd.DataFrame,
2525-
pd.DataFrame, pd.DataFrame, pd.DataFrame):
2527+
pd.DataFrame, pd.DataFrame, pd.DataFrame,
2528+
pd.DataFrame, pd.DataFrame, pd.DataFrame):
25262529

25272530
if br is None:
25282531
br = self._br

0 commit comments

Comments
 (0)