roboquant 2.4.1__tar.gz → 2.4.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.
- {roboquant-2.4.1 → roboquant-2.4.2}/PKG-INFO +2 -1
- {roboquant-2.4.1 → roboquant-2.4.2}/pyproject.toml +3 -2
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/account.py +23 -4
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/brokers/simbroker.py +15 -14
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/monetary.py +24 -12
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/order.py +12 -20
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/timeseries.py +3 -3
- {roboquant-2.4.1 → roboquant-2.4.2}/LICENSE +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/README.md +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ai/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ai/features.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ai/rl.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ai/strategies.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/alpaca/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/alpaca/broker.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/alpaca/feed.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/asset.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/brokers/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/brokers/broker.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/crypto/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/crypto/cryptobroker.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/crypto/cryptofeed.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/event.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/csvfeed.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/feed.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/historic.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/live.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/parquet.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/randomwalk.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/resources/us10.parquet +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/sql.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/util.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/feeds/yahoo.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ibkr/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ibkr/broker.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ibkr/types.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/alphabeta.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/basicjournal.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/feedmetric.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/journal.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/marketmetric.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/metric.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/metricsjournal.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/pnlmetric.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/pricemetric.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/runmetric.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/scorecard.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/journals/tensorboard.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/run.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/signal.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/buffer.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/cachedstrategy.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/emacrossover.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/ibsstrategy.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/multistrategy.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/strategy.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/strategies/tastrategy.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/ta/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/timeframe.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/traders/__init__.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/traders/flextrader.py +0 -0
- {roboquant-2.4.1 → roboquant-2.4.2}/roboquant/traders/trader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roboquant
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.2
|
|
4
4
|
Summary: A fast algorithmic trading platform with support for AI based strategies
|
|
5
5
|
Keywords: algorithmic,trading,machine learning,AI,investment,finance,crypto,stocks,exchange,forex
|
|
6
6
|
Author: roboquant team
|
|
@@ -23,6 +23,7 @@ Requires-Dist: requests>2.30.0
|
|
|
23
23
|
Requires-Dist: yfinance>1.5.0
|
|
24
24
|
Requires-Dist: pyarrow>24.0.0
|
|
25
25
|
Requires-Dist: ta-lib==0.6.5
|
|
26
|
+
Requires-Dist: pandas>=2.2.0
|
|
26
27
|
Requires-Dist: torch>=2.9.0 ; extra == 'ai'
|
|
27
28
|
Requires-Dist: tensorboard>=2.21.0 ; extra == 'ai'
|
|
28
29
|
Requires-Dist: stable-baselines3>=2.9.0 ; extra == 'ai'
|
|
@@ -22,7 +22,7 @@ module-name = "roboquant"
|
|
|
22
22
|
|
|
23
23
|
[project]
|
|
24
24
|
name = "roboquant"
|
|
25
|
-
version = "2.4.
|
|
25
|
+
version = "2.4.2"
|
|
26
26
|
authors = [{ name = "roboquant team", email = "info@roboquant.org" }]
|
|
27
27
|
description = "A fast algorithmic trading platform with support for AI based strategies"
|
|
28
28
|
readme = "README.md"
|
|
@@ -59,7 +59,8 @@ dependencies = [
|
|
|
59
59
|
"requests>2.30.0",
|
|
60
60
|
"yfinance>1.5.0",
|
|
61
61
|
"pyarrow>24.0.0",
|
|
62
|
-
"ta-lib==0.6.5"
|
|
62
|
+
"ta-lib==0.6.5",
|
|
63
|
+
"pandas>=2.2.0"
|
|
63
64
|
]
|
|
64
65
|
|
|
65
66
|
[project.optional-dependencies]
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
1
|
+
from dataclasses import dataclass, asdict
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from decimal import Decimal
|
|
4
4
|
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
5
7
|
from roboquant.asset import Asset
|
|
6
8
|
from roboquant.monetary import USD, Amount, Currency, Wallet
|
|
7
9
|
from roboquant.order import Order
|
|
@@ -24,8 +26,8 @@ class Trade:
|
|
|
24
26
|
asset: Asset
|
|
25
27
|
time: datetime
|
|
26
28
|
size: Decimal
|
|
27
|
-
price: float
|
|
28
|
-
pnl: float
|
|
29
|
+
price: float = float("nan")
|
|
30
|
+
pnl: float = float("nan")
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
@dataclass(slots=True)
|
|
@@ -40,9 +42,12 @@ class Position:
|
|
|
40
42
|
avg_price: float
|
|
41
43
|
"""Average price paid denoted in the currency of the asset"""
|
|
42
44
|
|
|
43
|
-
mkt_price: float
|
|
45
|
+
mkt_price: float = float("nan")
|
|
44
46
|
"""Latest market price denoted in the currency of the asset"""
|
|
45
47
|
|
|
48
|
+
pnl: float = float("nan")
|
|
49
|
+
"""The pnl for this position"""
|
|
50
|
+
|
|
46
51
|
@property
|
|
47
52
|
def is_short(self):
|
|
48
53
|
"""Return True if this is a short position, False otherwise"""
|
|
@@ -282,3 +287,17 @@ class Account:
|
|
|
282
287
|
f"last update : {self.last_update}"
|
|
283
288
|
)
|
|
284
289
|
return result
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def trades_to_dataframe(self) -> pd.DataFrame:
|
|
293
|
+
"""Return the trades as a dataframe"""
|
|
294
|
+
return pd.json_normalize([asdict(trade) for trade in self.trades])
|
|
295
|
+
|
|
296
|
+
def orders_to_dataframe(self)-> pd.DataFrame:
|
|
297
|
+
"""Return the orders as a dataframe"""
|
|
298
|
+
return pd.json_normalize([asdict(order) for order in self.orders])
|
|
299
|
+
|
|
300
|
+
def positions_to_dataframe(self)-> pd.DataFrame:
|
|
301
|
+
"""Return the positions as a dataframe"""
|
|
302
|
+
return pd.json_normalize([asdict(asset) | asdict(pos) for asset, pos in self.positions.items()])
|
|
303
|
+
|
|
@@ -134,8 +134,7 @@ class SimBroker(Broker):
|
|
|
134
134
|
"""Simulate a market execution and return a Trade object if the order has (partially) been executed."""
|
|
135
135
|
|
|
136
136
|
price = self._get_execution_price(order, item)
|
|
137
|
-
|
|
138
|
-
if executable:
|
|
137
|
+
if order.is_executable(price):
|
|
139
138
|
fill = self._get_fill(order, price)
|
|
140
139
|
fee = self._get_fee(Trade(order.asset, time, fill, price, 0.0))
|
|
141
140
|
pnl = self._pnl(order.asset, order.remaining, price) - fee
|
|
@@ -151,9 +150,10 @@ class SimBroker(Broker):
|
|
|
151
150
|
|
|
152
151
|
account.last_update = event.time
|
|
153
152
|
|
|
154
|
-
for asset,
|
|
153
|
+
for asset, pos in account.positions.items():
|
|
155
154
|
if price := event.get_price(asset, price_type):
|
|
156
|
-
|
|
155
|
+
pos.mkt_price = price
|
|
156
|
+
pos.pnl = asset.contract_value(pos.size, pos.avg_price - price)
|
|
157
157
|
|
|
158
158
|
def __next_order_id(self) -> str:
|
|
159
159
|
"""Generate a new order id. The order id is a simple integer that is incremented for each new order."""
|
|
@@ -181,9 +181,15 @@ class SimBroker(Broker):
|
|
|
181
181
|
del self._orders[order.id]
|
|
182
182
|
self._order_entry.pop(order.id)
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
|
|
185
|
+
def _fill_order(self, order: Order, trade: Trade) -> None:
|
|
186
|
+
"""Fill an order"""
|
|
187
|
+
new_fill = order.fill + trade.size
|
|
188
|
+
order = replace(order, fill = new_fill)
|
|
189
|
+
if order.remaining.is_zero():
|
|
190
|
+
self._remove_order(order)
|
|
191
|
+
else:
|
|
192
|
+
self._orders[order.id] = order
|
|
187
193
|
|
|
188
194
|
def _order_is_expired(self, order: Order, time: datetime) -> bool:
|
|
189
195
|
if order.tif == "GTC":
|
|
@@ -212,13 +218,8 @@ class SimBroker(Broker):
|
|
|
212
218
|
if trade is not None:
|
|
213
219
|
logger.info("executed order=%s trx=%s", order, trade)
|
|
214
220
|
self._update_account(trade)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if not order.remaining:
|
|
218
|
-
logger.info("completed order %s", order)
|
|
219
|
-
self._remove_order(order)
|
|
220
|
-
else:
|
|
221
|
-
self._update_order(order)
|
|
221
|
+
self._fill_order(order, trade)
|
|
222
|
+
|
|
222
223
|
|
|
223
224
|
def _calculate_open_orders(self) -> Wallet:
|
|
224
225
|
"""Calculate the buying power required for the open orders"""
|
|
@@ -19,8 +19,8 @@ logger = logging.getLogger(__name__)
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class Currency(str):
|
|
22
|
-
"""
|
|
23
|
-
differentiate between fiat- and crypto-currencies.
|
|
22
|
+
"""Represents a monetary currency and is a subclass of `str`.
|
|
23
|
+
It doesn't differentiate between fiat- and crypto-currencies.
|
|
24
24
|
|
|
25
25
|
It is possible to create an `Amount` using a combination of a `number` and a `Currency`:
|
|
26
26
|
```
|
|
@@ -138,18 +138,20 @@ class CurrencyConverter(ABC):
|
|
|
138
138
|
|
|
139
139
|
|
|
140
140
|
class NoConversion(CurrencyConverter):
|
|
141
|
-
"""The default currency converter that doesn't convert between currencies.
|
|
142
|
-
|
|
141
|
+
"""The default currency converter that doesn't convert between currencies.
|
|
142
|
+
If you don't trade in different currencies, this will be sufficient.
|
|
143
|
+
It will raise an exception if a conversion is required during a run."""
|
|
143
144
|
|
|
144
145
|
def convert(self, amount: "Amount", to_currency: Currency, dt: datetime) -> float:
|
|
145
|
-
"""Raise an error as no
|
|
146
|
+
"""Raise an error as no conversions are supported."""
|
|
146
147
|
raise NotImplementedError("The default NoConversion doesn't support any conversions")
|
|
147
148
|
|
|
148
149
|
|
|
149
150
|
class ECBConversion(CurrencyConverter):
|
|
150
151
|
"""CurrencyConverter that retrieves its exchange rates from the ECB (European Central Bank).
|
|
151
|
-
These exchange rates are based on the Euro and are updated daily by the ECB.
|
|
152
|
-
any historical data from before the Euro was introduced in 1999
|
|
152
|
+
These exchange rates are based on the Euro and are updated daily by the ECB.
|
|
153
|
+
They don't contain any historical data from before the Euro was introduced in 1999 and also
|
|
154
|
+
there is not support for crypto-currencies.
|
|
153
155
|
"""
|
|
154
156
|
|
|
155
157
|
__file_name = Path.home() / ".roboquant" / "eurofxref-hist.csv"
|
|
@@ -158,7 +160,7 @@ class ECBConversion(CurrencyConverter):
|
|
|
158
160
|
"""Initialize the ECBConversion.
|
|
159
161
|
|
|
160
162
|
Args:
|
|
161
|
-
force_download
|
|
163
|
+
force_download: Force download of the latest exchange rates if True.
|
|
162
164
|
"""
|
|
163
165
|
self._rates: Dict[Currency, List[Any]] = {}
|
|
164
166
|
if force_download or not self.up_to_date():
|
|
@@ -400,6 +402,8 @@ class Amount:
|
|
|
400
402
|
"""
|
|
401
403
|
return f"{self.value:{format_spec}}@{self.currency}"
|
|
402
404
|
|
|
405
|
+
def __bool__(self) -> bool:
|
|
406
|
+
return self.value.__bool__()
|
|
403
407
|
|
|
404
408
|
class Wallet(defaultdict[Currency, float]):
|
|
405
409
|
"""A wallet holds monetary values of different currencies.
|
|
@@ -500,6 +504,14 @@ class Wallet(defaultdict[Currency, float]):
|
|
|
500
504
|
result.update(self)
|
|
501
505
|
return result
|
|
502
506
|
|
|
507
|
+
def deposit(self, amount: Amount) -> None:
|
|
508
|
+
"""Deposit an amount into this wallet"""
|
|
509
|
+
self[amount.currency] += amount.value
|
|
510
|
+
|
|
511
|
+
def withdraw(self, amount: Amount) -> None:
|
|
512
|
+
"""Withdraw an amount from this wallet"""
|
|
513
|
+
self[amount.currency] -= amount.value
|
|
514
|
+
|
|
503
515
|
def convert_to(self, currency: Currency, dt: datetime) -> float:
|
|
504
516
|
"""Convert all the amounts held in this wallet to a single currency and return the value.
|
|
505
517
|
|
|
@@ -514,16 +526,16 @@ class Wallet(defaultdict[Currency, float]):
|
|
|
514
526
|
|
|
515
527
|
def __repr__(self) -> str:
|
|
516
528
|
"""Return a string representation of the wallet without any formatting on the
|
|
517
|
-
monetary values.
|
|
529
|
+
monetary values. Zero amounts will not be shown.
|
|
518
530
|
|
|
519
531
|
Returns:
|
|
520
532
|
The string representation.
|
|
521
533
|
"""
|
|
522
|
-
return " + ".join([f"{a}" for a in self.amounts()])
|
|
534
|
+
return " + ".join([f"{a}" for a in self.amounts() if a])
|
|
523
535
|
|
|
524
536
|
def __format__(self, format_spec: str) -> str:
|
|
525
537
|
"""Return a formatted string representation of the wallet. All the amounts
|
|
526
|
-
will be formatted according to the format_spec.
|
|
538
|
+
will be formatted according to the format_spec. Zero amounts will not be shown.
|
|
527
539
|
|
|
528
540
|
Args:
|
|
529
541
|
format_spec: The format specification, same as is used for float.
|
|
@@ -532,4 +544,4 @@ class Wallet(defaultdict[Currency, float]):
|
|
|
532
544
|
Returns:
|
|
533
545
|
The formatted string representation.
|
|
534
546
|
"""
|
|
535
|
-
return " + ".join([f"{a:{format_spec}}" for a in self.amounts()])
|
|
547
|
+
return " + ".join([f"{a:{format_spec}}" for a in self.amounts() if a])
|
|
@@ -21,7 +21,7 @@ class Order:
|
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
asset: Asset
|
|
24
|
-
"""The asset of this order."""
|
|
24
|
+
"""The underlying asset of this order."""
|
|
25
25
|
|
|
26
26
|
size: Decimal
|
|
27
27
|
"""The size (number of contracts) of the order. Positive for buy orders, negative for sell orders.
|
|
@@ -95,7 +95,7 @@ class Order:
|
|
|
95
95
|
|
|
96
96
|
def value(self) -> float:
|
|
97
97
|
"""
|
|
98
|
-
|
|
98
|
+
The total contract value of this order, it ignores the already filled part of the order.
|
|
99
99
|
|
|
100
100
|
Returns:
|
|
101
101
|
float: The total contract value of the order.
|
|
@@ -104,7 +104,7 @@ class Order:
|
|
|
104
104
|
|
|
105
105
|
def remaining_value(self) -> float:
|
|
106
106
|
"""
|
|
107
|
-
|
|
107
|
+
The remaining contract value of this order denoted in the currency of the asset.
|
|
108
108
|
|
|
109
109
|
Returns:
|
|
110
110
|
float: The remaining contract value of the order.
|
|
@@ -113,7 +113,7 @@ class Order:
|
|
|
113
113
|
|
|
114
114
|
def amount(self) -> Amount:
|
|
115
115
|
"""
|
|
116
|
-
|
|
116
|
+
The total market value of this order as a single Amount denoted in the currency of the asset.
|
|
117
117
|
|
|
118
118
|
Returns:
|
|
119
119
|
Amount: The total value of the order.
|
|
@@ -123,39 +123,31 @@ class Order:
|
|
|
123
123
|
@property
|
|
124
124
|
def is_buy(self) -> bool:
|
|
125
125
|
"""
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
bool: True if this is a BUY order, False otherwise.
|
|
126
|
+
True if this is a BUY order, False otherwise.
|
|
130
127
|
"""
|
|
131
128
|
return self.size > 0
|
|
132
129
|
|
|
133
130
|
@property
|
|
134
131
|
def is_sell(self) -> bool:
|
|
135
132
|
"""
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
Returns:
|
|
139
|
-
bool: True if this is a SELL order, False otherwise.
|
|
133
|
+
True if this is a SELL order, False otherwise.
|
|
140
134
|
"""
|
|
141
135
|
return self.size < 0
|
|
142
136
|
|
|
143
137
|
@property
|
|
144
138
|
def remaining(self) -> Decimal:
|
|
145
139
|
"""
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
Returns:
|
|
149
|
-
Decimal: The remaining order size.
|
|
140
|
+
The remaining order size that still needs to be filled.
|
|
150
141
|
"""
|
|
151
142
|
return self.size - self.fill
|
|
152
143
|
|
|
153
144
|
@property
|
|
154
145
|
def is_cancellation(self) -> bool:
|
|
155
146
|
"""
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
Returns:
|
|
159
|
-
bool: True if this is a cancellation order, False otherwise.
|
|
147
|
+
True if this is a cancellation order, False otherwise.
|
|
160
148
|
"""
|
|
161
149
|
return self.size.is_zero()
|
|
150
|
+
|
|
151
|
+
def is_executable(self, price: float) -> bool:
|
|
152
|
+
"""Will this order execute given the provided price"""
|
|
153
|
+
return price <= self.limit if self.is_buy else price >= self.limit
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import pandas as pd
|
|
6
6
|
|
|
7
|
+
from roboquant.timeframe import Timeframe
|
|
7
8
|
|
|
8
|
-
@dataclass
|
|
9
|
+
@dataclass(slots=True, frozen=True)
|
|
9
10
|
class TimeSeries:
|
|
10
11
|
"""A time series contains a name, a timeline and the values of the metric at each point in time. It
|
|
11
12
|
is used in several places in roboquant.
|
|
@@ -48,7 +49,6 @@ class TimeSeries:
|
|
|
48
49
|
"""Return the timeseries as a Pandas dataframe optionally with the time being the index
|
|
49
50
|
and the value being the column.
|
|
50
51
|
"""
|
|
51
|
-
import pandas as pd
|
|
52
52
|
|
|
53
53
|
d = {
|
|
54
54
|
"time": self.timeline,
|
|
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
|
|
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
|
|
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
|