bbstrader 0.1.3__tar.gz → 0.1.5__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.
Potentially problematic release.
This version of bbstrader might be problematic. Click here for more details.
- {bbstrader-0.1.3 → bbstrader-0.1.5}/PKG-INFO +4 -1
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/metatrader/account.py +32 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/metatrader/rates.py +11 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/metatrader/risk.py +52 -30
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/metatrader/trade.py +14 -10
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/metatrader/utils.py +1 -1
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader.egg-info/PKG-INFO +4 -1
- {bbstrader-0.1.3 → bbstrader-0.1.5}/setup.py +6 -1
- {bbstrader-0.1.3 → bbstrader-0.1.5}/LICENSE +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/README.md +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/__ini__.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/__init__.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/backtest.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/data.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/event.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/execution.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/performance.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/portfolio.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/btengine/strategy.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/metatrader/__init__.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/models/__init__.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/models/risk.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/strategies.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/trading/__init__.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/trading/execution.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/trading/run.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/trading/utils.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader/tseries.py +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader.egg-info/SOURCES.txt +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader.egg-info/dependency_links.txt +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader.egg-info/requires.txt +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/bbstrader.egg-info/top_level.txt +0 -0
- {bbstrader-0.1.3 → bbstrader-0.1.5}/setup.cfg +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bbstrader
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: Simplified Investment & Trading Toolkit
|
|
5
5
|
Home-page: https://github.com/bbalouki/bbstrader
|
|
6
|
+
Download-URL: https://pypi.org/project/bbstrader/
|
|
6
7
|
Author: Bertin Balouki SIMYELI
|
|
7
8
|
Author-email: <bertin@bbstrader.com>
|
|
8
9
|
Maintainer: Bertin Balouki SIMYELI
|
|
9
10
|
License: The MIT License (MIT)
|
|
11
|
+
Project-URL: Documentation, https://bbstrader.readthedocs.io/en/latest/
|
|
12
|
+
Project-URL: Source Code, https://github.com/bbalouki/bbstrader
|
|
10
13
|
Keywords: Finance,Toolkit,Financial,Analysis,Fundamental,Quantitative,Database,Equities,Currencies,Economics,ETFs,Funds,Indices,Moneymarkets,Commodities,Futures,CFDs,Derivatives,Trading,Investing,Portfolio,Optimization,Performance
|
|
11
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -615,6 +615,38 @@ class Account(object):
|
|
|
615
615
|
"""
|
|
616
616
|
self._show_info(self.get_tick_info, "tick", symbol=symbol)
|
|
617
617
|
|
|
618
|
+
def calculate_margin(self,
|
|
619
|
+
action: Literal['buy', 'sell'],
|
|
620
|
+
symbol: str,
|
|
621
|
+
lot: float,
|
|
622
|
+
price: float) -> float:
|
|
623
|
+
"""
|
|
624
|
+
Calculate margin required for an order.
|
|
625
|
+
|
|
626
|
+
Args:
|
|
627
|
+
action (str): The trading action, either 'buy' or 'sell'.
|
|
628
|
+
symbol (str): The symbol of the financial instrument.
|
|
629
|
+
lot (float): The lot size of the order.
|
|
630
|
+
price (float): The price of the order.
|
|
631
|
+
|
|
632
|
+
Returns:
|
|
633
|
+
float: The margin required for the order.
|
|
634
|
+
|
|
635
|
+
Raises:
|
|
636
|
+
MT5TerminalError: A specific exception based on the error code.
|
|
637
|
+
"""
|
|
638
|
+
_action = {
|
|
639
|
+
'buy': mt5.ORDER_TYPE_BUY,
|
|
640
|
+
'sell': mt5.ORDER_TYPE_SELL
|
|
641
|
+
}
|
|
642
|
+
try:
|
|
643
|
+
margin = mt5.order_calc_margin(_action[action], symbol, lot, price)
|
|
644
|
+
if margin is None:
|
|
645
|
+
return None
|
|
646
|
+
return margin
|
|
647
|
+
except Exception as e:
|
|
648
|
+
raise_mt5_error(e)
|
|
649
|
+
|
|
618
650
|
def check_order(self,
|
|
619
651
|
request: Dict[str, Any]) -> OrderCheckResult:
|
|
620
652
|
"""
|
|
@@ -191,6 +191,17 @@ class Rates(object):
|
|
|
191
191
|
|
|
192
192
|
@property
|
|
193
193
|
def get_returns(self):
|
|
194
|
+
"""
|
|
195
|
+
Fractional change between the current and a prior element.
|
|
196
|
+
|
|
197
|
+
Computes the fractional change from the immediately previous row by default.
|
|
198
|
+
This is useful in comparing the fraction of change in a time series of elements.
|
|
199
|
+
|
|
200
|
+
Note
|
|
201
|
+
----
|
|
202
|
+
It calculates fractional change (also known as `per unit change or relative change`)
|
|
203
|
+
and `not percentage change`. If you need the percentage change, multiply these values by 100.
|
|
204
|
+
"""
|
|
194
205
|
data = self.data.copy()
|
|
195
206
|
data['Returns'] = data['Adj Close'].pct_change()
|
|
196
207
|
data = data.dropna()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import random
|
|
2
|
+
import re
|
|
2
3
|
import numpy as np
|
|
3
4
|
from scipy.stats import norm
|
|
4
5
|
from datetime import datetime
|
|
@@ -67,6 +68,8 @@ class RiskManagement(Account):
|
|
|
67
68
|
max_trades: Optional[int] = None,
|
|
68
69
|
std_stop: bool = False,
|
|
69
70
|
pchange_sl: Optional[float] = None,
|
|
71
|
+
var_level: float = 0.95,
|
|
72
|
+
var_time_frame: TimeFrame = 'D1',
|
|
70
73
|
account_leverage: bool = True,
|
|
71
74
|
time_frame: TimeFrame = 'D1',
|
|
72
75
|
start_time: str = "1:00",
|
|
@@ -91,6 +94,9 @@ class RiskManagement(Account):
|
|
|
91
94
|
On `historical volatility` of the trading instrument. Defaults to False.
|
|
92
95
|
pchange_sl (float, optional): If set, the Stop loss is calculated based
|
|
93
96
|
On `percentage change` of the trading instrument.
|
|
97
|
+
var_level (float, optional): Confidence level for Value-at-Risk,e.g., 0.99 for 99% confidence interval.
|
|
98
|
+
The default is 0.95.
|
|
99
|
+
var_time_frame (str, optional): Time frame to use to calculate the VaR.
|
|
94
100
|
account_leverage (bool, optional): If set to True the account leverage will be used
|
|
95
101
|
In risk management setting. Defaults to False.
|
|
96
102
|
time_frame (str, optional): The time frame on which the program is working
|
|
@@ -118,7 +124,9 @@ class RiskManagement(Account):
|
|
|
118
124
|
if be is not None and (not isinstance(be, int) or be <= 0):
|
|
119
125
|
raise ValueError("be must be a positive integer number")
|
|
120
126
|
if time_frame not in TIMEFRAMES:
|
|
121
|
-
raise ValueError("Unsupported time frame")
|
|
127
|
+
raise ValueError("Unsupported time frame {}".format(time_frame))
|
|
128
|
+
if var_time_frame not in TIMEFRAMES:
|
|
129
|
+
raise ValueError("Unsupported time frame {}".format(var_time_frame))
|
|
122
130
|
|
|
123
131
|
self.symbol = symbol
|
|
124
132
|
self.start_time = start_time
|
|
@@ -126,6 +134,8 @@ class RiskManagement(Account):
|
|
|
126
134
|
self.max_trades = max_trades
|
|
127
135
|
self.std = std_stop
|
|
128
136
|
self.pchange = pchange_sl
|
|
137
|
+
self.var_level = var_level
|
|
138
|
+
self.var_tf = var_time_frame
|
|
129
139
|
self.daily_dd = daily_risk
|
|
130
140
|
self.max_risk = max_risk
|
|
131
141
|
self.rr = rr
|
|
@@ -136,8 +146,21 @@ class RiskManagement(Account):
|
|
|
136
146
|
self.account_leverage = account_leverage
|
|
137
147
|
self.symbol_info = super().get_symbol_info(self.symbol)
|
|
138
148
|
|
|
139
|
-
self.
|
|
140
|
-
|
|
149
|
+
self._tf = time_frame
|
|
150
|
+
|
|
151
|
+
def _convert_time_frame(self, tf: str) -> int:
|
|
152
|
+
"""Convert time frame to minutes"""
|
|
153
|
+
if tf == 'D1':
|
|
154
|
+
tf_int = self.get_minutes()
|
|
155
|
+
elif 'm' in tf:
|
|
156
|
+
tf_int = TIMEFRAMES[tf]
|
|
157
|
+
elif 'h' in tf:
|
|
158
|
+
tf_int = int(tf[0])*60
|
|
159
|
+
elif tf == 'W1':
|
|
160
|
+
tf_int = self.get_minutes() * 5
|
|
161
|
+
elif tf == 'MN1':
|
|
162
|
+
tf_int = self.get_minutes() * 22
|
|
163
|
+
return tf_int
|
|
141
164
|
|
|
142
165
|
def risk_level(self) -> float:
|
|
143
166
|
"""
|
|
@@ -194,10 +217,11 @@ class RiskManagement(Account):
|
|
|
194
217
|
def max_trade(self) -> int:
|
|
195
218
|
"""calculates the maximum number of trades allowed"""
|
|
196
219
|
minutes = self.get_minutes()
|
|
220
|
+
tf_int = self._convert_time_frame(self._tf)
|
|
197
221
|
if self.max_trades is not None:
|
|
198
222
|
max_trades = self.max_trades
|
|
199
223
|
else:
|
|
200
|
-
max_trades = round(minutes /
|
|
224
|
+
max_trades = round(minutes / tf_int)
|
|
201
225
|
return max(max_trades, 1)
|
|
202
226
|
|
|
203
227
|
def get_minutes(self) -> int:
|
|
@@ -217,24 +241,22 @@ class RiskManagement(Account):
|
|
|
217
241
|
|
|
218
242
|
return hours
|
|
219
243
|
|
|
220
|
-
def get_std_stop(self
|
|
244
|
+
def get_std_stop(self):
|
|
221
245
|
"""
|
|
222
246
|
Calculate the standard deviation-based stop loss level
|
|
223
247
|
for a given financial instrument.
|
|
224
248
|
|
|
225
|
-
Args:
|
|
226
|
-
tf (str): Timeframe for data, default is 'D1' (Daily).
|
|
227
|
-
interval (int): Number of historical data points to consider
|
|
228
|
-
for calculating standard deviation, default is 252.
|
|
229
|
-
|
|
230
249
|
Returns:
|
|
231
250
|
- Standard deviation-based stop loss level, rounded to the nearest point.
|
|
232
251
|
- 0 if the calculated stop loss is less than or equal to 0.
|
|
233
252
|
"""
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
253
|
+
minutes = self.get_minutes()
|
|
254
|
+
tf_int = self._convert_time_frame(self._tf)
|
|
255
|
+
interval = round((minutes / tf_int) * 252)
|
|
256
|
+
|
|
257
|
+
rate = Rates(self.symbol, self._tf, 0, interval)
|
|
258
|
+
returns = rate.get_returns*100
|
|
259
|
+
std = returns.std()
|
|
238
260
|
point = self.get_symbol_info(self.symbol).point
|
|
239
261
|
av_price = (self.symbol_info.bid + self.symbol_info.ask)/2
|
|
240
262
|
price_interval = av_price * ((100-std))/100
|
|
@@ -271,26 +293,27 @@ class RiskManagement(Account):
|
|
|
271
293
|
# Use std as default pchange
|
|
272
294
|
return self.get_std_stop()
|
|
273
295
|
|
|
274
|
-
def calculate_var(self, tf: TimeFrame = 'D1',
|
|
296
|
+
def calculate_var(self, tf: TimeFrame = 'D1', c=0.95):
|
|
275
297
|
"""
|
|
276
298
|
Calculate Value at Risk (VaR) for a given portfolio.
|
|
277
299
|
|
|
278
300
|
Args:
|
|
279
301
|
tf (str): Time frame to use to calculate volatility.
|
|
280
|
-
interval (int): How many periods to use based on time frame.
|
|
281
302
|
c (float): Confidence level for VaR calculation (default is 95%).
|
|
282
303
|
|
|
283
304
|
Returns:
|
|
284
305
|
- VaR value
|
|
285
306
|
"""
|
|
307
|
+
minutes = self.get_minutes()
|
|
308
|
+
tf_int = self._convert_time_frame(tf)
|
|
309
|
+
interval = round((minutes / tf_int) * 252)
|
|
310
|
+
|
|
286
311
|
rate = Rates(self.symbol, tf, 0, interval)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
sigma = np.std(prices['return'])
|
|
293
|
-
var = self.var_cov_var(P, c, mu, sigma)
|
|
312
|
+
returns = rate.get_returns*100
|
|
313
|
+
p = self.get_account_info().margin_free
|
|
314
|
+
mu = returns.mean()
|
|
315
|
+
sigma = returns.std()
|
|
316
|
+
var = self.var_cov_var(p, c, mu, sigma)
|
|
294
317
|
return var
|
|
295
318
|
|
|
296
319
|
def var_cov_var(self, P: float, c: float, mu: float, sigma: float):
|
|
@@ -312,11 +335,15 @@ class RiskManagement(Account):
|
|
|
312
335
|
def var_loss_value(self):
|
|
313
336
|
"""
|
|
314
337
|
Calculate the stop-loss level based on VaR.
|
|
338
|
+
|
|
339
|
+
Notes:
|
|
340
|
+
The Var is Estimated using the Variance-Covariance method on the daily returns.
|
|
341
|
+
If you want to use the VaR for a different time frame .
|
|
315
342
|
"""
|
|
316
343
|
P = self.get_account_info().margin_free
|
|
317
344
|
trade_risk = self.get_trade_risk()
|
|
318
345
|
loss_allowed = P * trade_risk
|
|
319
|
-
var = self.calculate_var()
|
|
346
|
+
var = self.calculate_var(c=self.var_level, tf=self.var_tf)
|
|
320
347
|
return min(var, loss_allowed)
|
|
321
348
|
|
|
322
349
|
def get_take_profit(self) -> int:
|
|
@@ -480,13 +507,8 @@ class RiskManagement(Account):
|
|
|
480
507
|
if self.get_symbol_type(self.symbol) == 'IDX':
|
|
481
508
|
rates = self.get_currency_rates(self.symbol)
|
|
482
509
|
if rates['mc'] == rates['pc'] == 'JPY':
|
|
483
|
-
if self.std:
|
|
484
|
-
raise ValueError(
|
|
485
|
-
f"""Please Set std=False or use pchange_sl=True
|
|
486
|
-
or set sl=value or use the default method calculation for {self.symbol}
|
|
487
|
-
Currency risk"""
|
|
488
|
-
)
|
|
489
510
|
lot = lot * contract_size
|
|
511
|
+
lot = self._check_lot(lot)
|
|
490
512
|
volume = round(lot * av_price * contract_size)
|
|
491
513
|
if contract_size == 1:
|
|
492
514
|
volume = round(lot * av_price)
|
|
@@ -555,7 +555,7 @@ class Trade(RiskManagement):
|
|
|
555
555
|
check_result = self.check_order(request)
|
|
556
556
|
result = self.send_order(request)
|
|
557
557
|
except Exception as e:
|
|
558
|
-
print(f"{self.
|
|
558
|
+
print(f"{self.current_datetime()} -", end=' ')
|
|
559
559
|
trade_retcode_message(
|
|
560
560
|
result.retcode, display=True, add_msg=f"{e}{addtionnal}")
|
|
561
561
|
if result.retcode != Mt5.TRADE_RETCODE_DONE:
|
|
@@ -571,7 +571,7 @@ class Trade(RiskManagement):
|
|
|
571
571
|
check_result = self.check_order(request)
|
|
572
572
|
result = self.send_order(request)
|
|
573
573
|
except Exception as e:
|
|
574
|
-
print(f"{self.
|
|
574
|
+
print(f"{self.current_datetime()} -", end=' ')
|
|
575
575
|
trade_retcode_message(
|
|
576
576
|
result.retcode, display=True, add_msg=f"{e}{addtionnal}")
|
|
577
577
|
if result.retcode == Mt5.TRADE_RETCODE_DONE:
|
|
@@ -900,7 +900,7 @@ class Trade(RiskManagement):
|
|
|
900
900
|
check_result = self.check_order(request)
|
|
901
901
|
result = self.send_order(request)
|
|
902
902
|
except Exception as e:
|
|
903
|
-
print(f"{self.
|
|
903
|
+
print(f"{self.current_datetime()} -", end=' ')
|
|
904
904
|
trade_retcode_message(
|
|
905
905
|
result.retcode, display=True, add_msg=f"{e}{addtionnal}")
|
|
906
906
|
if result.retcode != Mt5.TRADE_RETCODE_DONE:
|
|
@@ -917,7 +917,7 @@ class Trade(RiskManagement):
|
|
|
917
917
|
check_result = self.check_order(request)
|
|
918
918
|
result = self.send_order(request)
|
|
919
919
|
except Exception as e:
|
|
920
|
-
print(f"{self.
|
|
920
|
+
print(f"{self.current_datetime()} -", end=' ')
|
|
921
921
|
trade_retcode_message(
|
|
922
922
|
result.retcode, display=True, add_msg=f"{e}{addtionnal}")
|
|
923
923
|
if result.retcode == Mt5.TRADE_RETCODE_DONE:
|
|
@@ -1041,7 +1041,7 @@ class Trade(RiskManagement):
|
|
|
1041
1041
|
check_result = self.check_order(request)
|
|
1042
1042
|
result = self.send_order(request)
|
|
1043
1043
|
except Exception as e:
|
|
1044
|
-
print(f"{self.
|
|
1044
|
+
print(f"{self.current_datetime()} -", end=' ')
|
|
1045
1045
|
trade_retcode_message(
|
|
1046
1046
|
result.retcode, display=True, add_msg=f"{e}{addtionnal}")
|
|
1047
1047
|
if result.retcode != Mt5.TRADE_RETCODE_DONE:
|
|
@@ -1055,7 +1055,7 @@ class Trade(RiskManagement):
|
|
|
1055
1055
|
check_result = self.check_order(request)
|
|
1056
1056
|
result = self.send_order(request)
|
|
1057
1057
|
except Exception as e:
|
|
1058
|
-
print(f"{self.
|
|
1058
|
+
print(f"{self.current_datetime()} -", end=' ')
|
|
1059
1059
|
trade_retcode_message(
|
|
1060
1060
|
result.retcode, display=True, add_msg=f"{e}{addtionnal}")
|
|
1061
1061
|
if result.retcode == Mt5.TRADE_RETCODE_DONE:
|
|
@@ -1250,7 +1250,7 @@ class Trade(RiskManagement):
|
|
|
1250
1250
|
def sleep_time(self, weekend=False):
|
|
1251
1251
|
if weekend:
|
|
1252
1252
|
# claculate number of minute from the friday and to monday start
|
|
1253
|
-
friday_time = datetime.strptime(self.
|
|
1253
|
+
friday_time = datetime.strptime(self.current_time(), '%H:%M')
|
|
1254
1254
|
monday_time = datetime.strptime(self.start, '%H:%M')
|
|
1255
1255
|
intra_day_diff = (monday_time - friday_time).total_seconds() // 60
|
|
1256
1256
|
inter_day_diff = 3 * 24 * 60
|
|
@@ -1259,14 +1259,18 @@ class Trade(RiskManagement):
|
|
|
1259
1259
|
else:
|
|
1260
1260
|
# claculate number of minute from the end to the start
|
|
1261
1261
|
start = datetime.strptime(self.start, '%H:%M')
|
|
1262
|
-
end =
|
|
1262
|
+
end = datetime.strptime(self.current_time(), '%H:%M')
|
|
1263
1263
|
minutes = (end - start).total_seconds() // 60
|
|
1264
1264
|
sleep_time = (24*60) - minutes
|
|
1265
1265
|
return sleep_time
|
|
1266
1266
|
|
|
1267
|
-
def
|
|
1267
|
+
def current_datetime(self):
|
|
1268
1268
|
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
1269
|
-
|
|
1269
|
+
|
|
1270
|
+
def current_time(self, seconds=False):
|
|
1271
|
+
if seconds:
|
|
1272
|
+
return datetime.now().strftime("%H:%M:%S")
|
|
1273
|
+
return datetime.now().strftime("%H:%M")
|
|
1270
1274
|
|
|
1271
1275
|
def create_trade_instance(
|
|
1272
1276
|
symbols: List[str],
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bbstrader
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: Simplified Investment & Trading Toolkit
|
|
5
5
|
Home-page: https://github.com/bbalouki/bbstrader
|
|
6
|
+
Download-URL: https://pypi.org/project/bbstrader/
|
|
6
7
|
Author: Bertin Balouki SIMYELI
|
|
7
8
|
Author-email: <bertin@bbstrader.com>
|
|
8
9
|
Maintainer: Bertin Balouki SIMYELI
|
|
9
10
|
License: The MIT License (MIT)
|
|
11
|
+
Project-URL: Documentation, https://bbstrader.readthedocs.io/en/latest/
|
|
12
|
+
Project-URL: Source Code, https://github.com/bbalouki/bbstrader
|
|
10
13
|
Keywords: Finance,Toolkit,Financial,Analysis,Fundamental,Quantitative,Database,Equities,Currencies,Economics,ETFs,Funds,Indices,Moneymarkets,Commodities,Futures,CFDs,Derivatives,Trading,Investing,Portfolio,Optimization,Performance
|
|
11
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -7,7 +7,7 @@ if sys.version_info < (3, 10):
|
|
|
7
7
|
with open("README.md", encoding="utf-8") as fh:
|
|
8
8
|
long_description = fh.read()
|
|
9
9
|
|
|
10
|
-
VERSION = '0.1.
|
|
10
|
+
VERSION = '0.1.05'
|
|
11
11
|
DESCRIPTION = 'Simplified Investment & Trading Toolkit'
|
|
12
12
|
|
|
13
13
|
KEYWORDS = [
|
|
@@ -44,6 +44,11 @@ setup(
|
|
|
44
44
|
version=VERSION,
|
|
45
45
|
author='Bertin Balouki SIMYELI',
|
|
46
46
|
url='https://github.com/bbalouki/bbstrader',
|
|
47
|
+
download_url='https://pypi.org/project/bbstrader/',
|
|
48
|
+
project_urls={
|
|
49
|
+
"Documentation": "https://bbstrader.readthedocs.io/en/latest/",
|
|
50
|
+
"Source Code": "https://github.com/bbalouki/bbstrader",
|
|
51
|
+
},
|
|
47
52
|
license='The MIT License (MIT)',
|
|
48
53
|
author_email='<bertin@bbstrader.com>',
|
|
49
54
|
maintainer='Bertin Balouki SIMYELI',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|