Skip to content

Commit

Permalink
tracker => journal
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaron committed Feb 25, 2024
1 parent 5c13a8f commit 92e3508
Show file tree
Hide file tree
Showing 24 changed files with 76 additions and 77 deletions.
2 changes: 1 addition & 1 deletion roboquant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@

from roboquant import brokers
from roboquant import traders
from roboquant import trackers
from roboquant import journals
from roboquant import strategies
from roboquant import feeds
2 changes: 1 addition & 1 deletion roboquant/feeds/candlefeed.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


class CandleFeed(Feed):
"""Aggregates Trades of another feed into Candles"""
"""Aggregates Trades of another feed into candles"""

def __init__(self, feed: Feed, frequency: timedelta, send_remaining=False):
super().__init__()
Expand Down
9 changes: 9 additions & 0 deletions roboquant/journals/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from roboquant.journals.journal import Journal
from roboquant.journals.alphabeta import AlphaBeta
from roboquant.journals.basicjournal import BasicJournal
from roboquant.journals.tensorboardjournal import TensorboardJournal
from roboquant.journals.runmetric import RunMetric
from roboquant.journals.equitymetric import EquityMetric
from roboquant.journals.metric import Metric
from roboquant.journals.feedmetric import FeedMetric
from roboquant.journals.pricemetric import PriceItemMetric
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from roboquant.trackers.tracker import Tracker
from roboquant.journals.journal import Journal
import inspect


class BasicTracker(Tracker):
class BasicJournal(Journal):
"""Tracks a number of basic metrics:
- total number of events, items, signals and orders until that time
- total pnl percentage
This tracker adds little overhead to a run, both CPU and memory wise.
This journal adds little overhead to a run, both CPU and memory wise.
"""

def __init__(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from roboquant.trackers.metric import Metric
from roboquant.journals.metric import Metric


class EquityMetric(Metric):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from roboquant.trackers.metric import Metric
from roboquant.journals.metric import Metric


class FeedMetric(Metric):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from roboquant.signal import Signal


class Tracker(Protocol):
class Journal(Protocol):
"""
A tracker allows for the tracking and/or logging of one or more metrics during a run.
A journal allows for the tracking and/or logging of one or more metrics during a run.
"""

def track(self, event: Event, account: Account, signals: dict[str, Signal], orders: list[Order]):
"""invoked at each step of a run that provides the tracker with the opportunity to
"""invoked at each step of a run that provides the journal with the opportunity to
track and log various metrics."""
...
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from roboquant.trackers.metric import Metric
from roboquant.trackers.tracker import Tracker
from roboquant.journals.metric import Metric
from roboquant.journals.journal import Journal
from datetime import datetime


class MetricsTracker(Tracker):
class MetricsJournal(Journal):
"""
A journal that allows for metrics to be added and calculated at each step. It will store
the results in memory.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from roboquant.trackers.metric import Metric
from roboquant.journals.metric import Metric


class PriceItemMetric(Metric):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from roboquant.trackers.metric import Metric
from roboquant.journals.metric import Metric


class RunMetric(Metric):
"""Tracks a number of basic progress metrics:
"""Calculates a number of basic metrics during a run:
- total number of events, items, signals and orders
This tracker adds little overhead to a run, both CPU and memory wise.
"""

def __init__(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from roboquant.trackers import Tracker
from roboquant.trackers.metric import Metric
from roboquant.journals import Journal
from roboquant.journals.metric import Metric


class TensorboardTracker(Tracker):
class TensorboardJournal(Journal):
"""Record metrics to a Tensorboard compatible file.
This can be used outside the realm of machine learning, but requires tensorboard to be installed.
Expand Down
10 changes: 5 additions & 5 deletions roboquant/roboquant.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from roboquant.brokers.broker import Broker
from roboquant.feeds.feed import Feed
from roboquant.traders.trader import Trader
from roboquant.trackers.tracker import Tracker
from roboquant.journals.journal import Journal
from roboquant.feeds.eventchannel import EventChannel
from .timeframe import Timeframe
from roboquant.brokers.simbroker import SimBroker
Expand Down Expand Up @@ -39,7 +39,7 @@ def __init__(
def run(
self,
feed: Feed,
tracker: Tracker | None = None,
journal: Journal | None = None,
timeframe: Timeframe | None = None,
capacity: int = 10,
heartbeat_timeout: float | None = None,
Expand All @@ -49,7 +49,7 @@ def run(
Args:
- feed: the feed to use for this run. This is the only mandatory argument.
- tracker: tracker to use to log and/or store progress and metrics, default is None.
- journal: journal to use to log and/or store progress and metrics, default is None.
- timeframe: optionally limit the run to events within this timeframe. The default is None, resulting in all
events in the feed being delivered.
- capacity: the buffer capacity of the event channel before it starts blocking new events. Default is 10 events.
Expand All @@ -65,7 +65,7 @@ def run(
account = self.broker.sync(event)
orders = self.trader.create_orders(signals, event, account)
self.broker.place_orders(*orders)
if tracker:
tracker.track(event, account, signals, orders)
if journal:
journal.track(event, account, signals, orders)

return self.broker.sync()
9 changes: 0 additions & 9 deletions roboquant/trackers/__init__.py

This file was deleted.

8 changes: 4 additions & 4 deletions tests/performance/bigcsvfeed_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@
feed = rq.feeds.CSVFeed.stooq_us_daily(path)
loadtime = time.time() - start
roboquant = rq.Roboquant(rq.strategies.EMACrossover(13, 26))
tracker = rq.trackers.BasicTracker()
journal = rq.journals.BasicJournal()
start = time.time()
account = roboquant.run(feed, tracker=tracker)
account = roboquant.run(feed, journal=journal)
runtime = time.time() - start

print(account)
print(tracker)
print(journal)

# Print statistics
print()
print(f"load time = {loadtime:.1f}s")
print("files =", len(feed.symbols))
print(f"throughput = {len(feed.symbols) / loadtime:.0f} files/s")
print(f"run time = {runtime:.1f}s")
candles = tracker.items
candles = journal.items
print(f"candles = {(candles / 1_000_000):.1f}M")
throughput = candles / (runtime * 1_000_000)
print(f"throughput = {throughput:.1f}M candles/s")
Expand Down
12 changes: 6 additions & 6 deletions tests/performance/profiling_test.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from cProfile import Profile
import os
from pstats import Stats, SortKey
import roboquant as rq

from roboquant import Roboquant, CSVFeed, BasicTracker, EMACrossover

if __name__ == "__main__":
path = os.path.expanduser("~/data/nasdaq_stocks/1")
feed = CSVFeed.stooq_us_daily(path)
feed = rq.feeds.CSVFeed.stooq_us_daily(path)
print("timeframe =", feed.timeframe(), " symbols =", len(feed.symbols))
rq = Roboquant(EMACrossover(13, 26))
tracker = BasicTracker()
roboquant = rq.Roboquant(rq.strategies.EMACrossover(13, 26))
journal = rq.journals.BasicJournal()

# Profile the run to detect bottlenecks
with Profile() as profile:
rq.run(feed, tracker=tracker)
print(tracker)
roboquant.run(feed, journal)
print(f"\n{journal}")
Stats(profile).sort_stats(SortKey.TIME).print_stats()
4 changes: 3 additions & 1 deletion tests/performance/tiingodelay_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import logging
import time

from roboquant import EventChannel, Timeframe, TiingoLiveFeed, feedutil
from roboquant import Timeframe
from roboquant.feeds import EventChannel, TiingoLiveFeed, feedutil
from statistics import mean, stdev


if __name__ == "__main__":

logging.basicConfig(level=logging.INFO)
Expand Down
6 changes: 3 additions & 3 deletions tests/samples/papertrade_tiingo_ibkr.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
# Lets run our EMACrossover strategy for 15 minutes
roboquant = rq.Roboquant(rq.strategies.EMACrossover(3, 5), broker=ibkr)
timeframe = rq.Timeframe.next(minutes=15)
tracker = rq.trackers.BasicTracker()
account = roboquant.run(feed, tracker, timeframe)
journal = rq.journals.BasicJournal()
account = roboquant.run(feed, journal, timeframe)
src_feed.close()

print(account)
print(tracker)
print(journal)
sys.exit(0)
6 changes: 3 additions & 3 deletions tests/samples/tensorboard_metrics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from roboquant import Roboquant
from roboquant.feeds import YahooFeed
from roboquant.strategies import EMACrossover
from roboquant.trackers import TensorboardTracker, EquityMetric, RunMetric, FeedMetric, PriceItemMetric, AlphaBeta
from roboquant.journals import TensorboardJournal, EquityMetric, RunMetric, FeedMetric, PriceItemMetric, AlphaBeta
from tensorboard.summary import Writer

if __name__ == "__main__":
Expand All @@ -15,6 +15,6 @@
rq = Roboquant(EMACrossover(p1, p2))
log_dir = f"""runs/ema_{p1}_{p2}"""
writer = Writer(log_dir)
tracker = TensorboardTracker(writer, EquityMetric(), RunMetric(), FeedMetric(), PriceItemMetric("JPM"), AlphaBeta(200))
account = rq.run(feed, tracker)
journal = TensorboardJournal(writer, EquityMetric(), RunMetric(), FeedMetric(), PriceItemMetric("JPM"), AlphaBeta(200))
account = rq.run(feed, journal)
writer.close()
15 changes: 7 additions & 8 deletions tests/samples/walkforward.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
from roboquant import Roboquant, EMACrossover, EquityTracker, YahooFeed
import roboquant as rq


if __name__ == "__main__":
feed = YahooFeed("JPM", "IBM", "F", start_date="2000-01-01")
feed = rq.feeds.YahooFeed("JPM", "IBM", "F", start_date="2000-01-01")

# split the feed timeframe in 4 equal parts
timeframes = feed.timeframe().split(4)

# run a back-test on each timeframe
for timeframe in timeframes:
rq = Roboquant(EMACrossover(13, 26))
tracker = EquityTracker()
rq.run(feed, tracker, timeframe)
pnl = tracker.pnl() * 100
mdd = tracker.max_drawdown() * 100
print(f"{timeframe} pnl={pnl:5.2f}% mdd={mdd:5.2f}%")
roboquant = rq.Roboquant(rq.strategies.EMACrossover(13, 26))
journal = rq.journals.BasicJournal()
roboquant.run(feed, journal, timeframe)
pnl = journal.pnl * 100.0
print(f"{timeframe} pnl={pnl:5.2f}%")
14 changes: 7 additions & 7 deletions tests/unit/test_flextrader.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from roboquant import Roboquant, Order, PriceItem
from roboquant.strategies import EMACrossover
from roboquant.trackers import BasicTracker
from roboquant.journals import BasicJournal
from roboquant.traders import FlexTrader
from tests.common import get_feed

Expand All @@ -24,16 +24,16 @@ class TestFlexTrader(unittest.TestCase):
def test_default_flextrader(self):
feed = get_feed()
rq = Roboquant(EMACrossover(13, 26), trader=FlexTrader())
tracker = BasicTracker()
rq.run(feed, tracker=tracker)
self.assertGreater(tracker.orders, 0)
journal = BasicJournal()
rq.run(feed, journal=journal)
self.assertGreater(journal.orders, 0)

def test_custom_flextrader(self):
feed = get_feed()
rq = Roboquant(EMACrossover(13, 26), trader=_MyTrader())
tracker = BasicTracker()
rq.run(feed, tracker=tracker)
self.assertGreater(tracker.orders, 0)
journal = BasicJournal()
rq.run(feed, journal=journal)
self.assertGreater(journal.orders, 0)


if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions tests/unit/test_rnnstrategy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest
from roboquant import Roboquant, Timeframe
from roboquant.traders import FlexTrader
from roboquant.trackers import BasicTracker
from roboquant.journals import BasicJournal

from roboquant.strategies.rnnstrategy import RNNStrategy
import torch.nn as nn
Expand Down Expand Up @@ -43,10 +43,10 @@ def test_lstm_model(self):
# Run the trained model with the last 4 years of data
rq = Roboquant(strategy, FlexTrader(max_order_perc=0.8))
tf = Timeframe.fromisoformat("2020-01-01", "2023-12-31")
tracker = BasicTracker()
rq.run(feed, tracker, tf)
self.assertGreater(tracker.signals, 0)
# print(tracker)
journal = BasicJournal()
rq.run(feed, journal, tf)
self.assertGreater(journal.signals, 0)
# print(journal)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
import unittest
from roboquant import Roboquant
from roboquant.strategies import EMACrossover
from roboquant.trackers import RunMetric, EquityMetric, TensorboardTracker
from roboquant.journals import RunMetric, EquityMetric, TensorboardJournal
from tests.common import get_feed
from tensorboard.summary import Writer


class TestTensorboardTracker(unittest.TestCase):
class TestTensorboard(unittest.TestCase):

def test_tensorboardtracker(self):
def test_tensorboard_journal(self):
rq = Roboquant(EMACrossover())
feed = get_feed()

tmpdir = tempfile.gettempdir()

output = Path(tmpdir).joinpath("runs")
writer = Writer(str(output))
tracker = TensorboardTracker(writer, RunMetric(), EquityMetric())
rq.run(feed, tracker=tracker)
journal = TensorboardJournal(writer, RunMetric(), EquityMetric())
rq.run(feed, journal=journal)
writer.close()


Expand Down

0 comments on commit 92e3508

Please sign in to comment.