@@ -73,18 +73,30 @@ This will create:
73
73
---
74
74
75
75
## 📈 Example: A Simple Trading Bot
76
- The following example connects to Binance and buys BTC every 2 hours.
76
+ The following example trading bot implements a simple moving average strategy.
77
+ The strategy will use data from bitvavo exchange and will calculate
78
+ the 20, 50 and 100 period exponential moving averages (EMA) and the
79
+ 14 period relative strength index (RSI).
80
+
81
+ > This example uses [ PyIndicators] ( https://github.com/coding-kitties/pyindicators ) for technical analysis.
82
+ > This dependency is not part of the framework, but is used to perform technical analysis on the dataframes.
83
+ > You can install it using pip: pip install pyindicators.
84
+
85
+ ``` bash
77
86
78
87
` ` ` python
79
88
import logging.config
80
89
from dotenv import load_dotenv
81
90
91
+ from pyindicators import ema, rsi
92
+
82
93
from investing_algorithm_framework import create_app, TimeUnit, Context, BacktestDateRange, \
83
94
CCXTOHLCVMarketDataSource, CCXTTickerMarketDataSource, DEFAULT_LOGGING_CONFIG, \
84
- TradingStrategy, SnapshotInterval
95
+ TradingStrategy, SnapshotInterval, convert_polars_to_pandas
85
96
86
97
load_dotenv ()
87
98
logging.config.dictConfig(DEFAULT_LOGGING_CONFIG)
99
+ logger = logging.getLogger(__name__)
88
100
89
101
# OHLCV data for candles
90
102
bitvavo_btc_eur_ohlcv_2h = CCXTOHLCVMarketDataSource(
@@ -111,21 +123,58 @@ class MyStrategy(TradingStrategy):
111
123
data_sources = [bitvavo_btc_eur_ohlcv_2h, bitvavo_btc_eur_ticker]
112
124
113
125
def run_strategy(self, context: Context, market_data):
114
- # Access the data sources with the indentifier
115
- polars_df = market_data[" BTC-ohlcv" ]
116
- ticker_data = market_data[" BTC-ticker" ]
117
- unallocated_balance = context.get_unallocated()
118
- positions = context.get_positions()
119
- trades = context.get_trades()
120
- open_trades = context.get_open_trades()
121
- closed_trades = context.get_closed_trades()
126
+
127
+ if context.has_open_orders(target_symbol=" BTC" ):
128
+ logger.info(" There are open orders, skipping strategy iteration." )
129
+ return
130
+
131
+ print(market_data)
132
+
133
+ data = convert_polars_to_pandas(market_data[" BTC-ohlcv" ])
134
+ data = ema(data, source_column=" Close" , period=20, result_column=" ema_20" )
135
+ data = ema(data, source_column=" Close" , period=50, result_column=" ema_50" )
136
+ data = ema(data, source_column=" Close" , period=100, result_column=" ema_100" )
137
+ data = rsi(data, source_column=" Close" , period=14, result_column=" rsi_14" )
138
+
139
+ if context.has_position(" BTC" ) and self.sell_signal(data):
140
+ context.create_limit_sell_order(
141
+ " BTC" , percentage_of_position=100, price=data[" Close" ].iloc[-1]
142
+ )
143
+ return
144
+
145
+ if not context.has_position(" BTC" ) and self.buy_signal(data):
146
+ context.create_limit_buy_order(
147
+ " BTC" , percentage_of_portfolio=20, price=data[" Close" ].iloc[-1]
148
+ )
149
+ return
150
+
151
+ def buy_signal(self, data):
152
+ if len(data) < 100:
153
+ return False
154
+ last_row = data.iloc[-1]
155
+ if last_row[" ema_20" ] > last_row[" ema_50" ] and last_row[" ema_50" ] > last_row[" ema_100" ]:
156
+ return True
157
+ return False
158
+
159
+ def sell_signal(self, data):
160
+
161
+ if data[" ema_20" ].iloc[-1] < data[" ema_50" ].iloc[-1] and \
162
+ data[" ema_20" ].iloc[-2] > = data[" ema_50" ].iloc[-2]:
163
+ return True
164
+
165
+ return False
122
166
123
167
date_range = BacktestDateRange(
124
- start_date = " 2023-08-24 00:00:00" ,
125
- end_date = " 2023-12-02 00:00:00"
168
+ start_date=" 2023-08-24 00:00:00" , end_date=" 2023-12-02 00:00:00"
126
169
)
127
- backtest_report = app.run_backtest(backtest_date_range = date_range, initial_amount = 100 , snapshot_interval = SnapshotInterval.STRATEGY_ITERATION )
128
- backtest_report.show()
170
+ app.add_strategy(MyStrategy)
171
+
172
+ if __name__ == " __main__" :
173
+ # Run the backtest with a daily snapshot interval for end-of-day granular reporting
174
+ backtest_report = app.run_backtest(
175
+ backtest_date_range=date_range, initial_amount=100, snapshot_interval=SnapshotInterval.STRATEGY_ITERATION
176
+ )
177
+ backtest_report.show ()
129
178
` ` `
130
179
131
180
> You can find more examples [here](./examples) folder.
0 commit comments