From 9e914561c90924795e9191d197dfb752194ec219 Mon Sep 17 00:00:00 2001 From: Adam Glustein Date: Tue, 16 Jul 2024 12:33:58 -0400 Subject: [PATCH] Rewrite documentation to be less focused on finance examples; fix a wide set of issues and missing parts in the docs Signed-off-by: Adam Glustein --- docs/wiki/api-references/csp.profiler-API.md | 1 + docs/wiki/concepts/CSP-Graph.md | 106 ++++++----- docs/wiki/concepts/CSP-Node.md | 9 +- docs/wiki/get-started/First-Steps.md | 106 +++++------ docs/wiki/get-started/IO-with-Adapters.md | 26 ++- docs/wiki/get-started/More-with-CSP.md | 184 ++++++++----------- docs/wiki/images/corr-graph.png | Bin 0 -> 63004 bytes docs/wiki/images/corr-trend.png | Bin 0 -> 17077 bytes docs/wiki/images/monitor-graph.png | Bin 0 -> 10324 bytes 9 files changed, 200 insertions(+), 232 deletions(-) create mode 100644 docs/wiki/images/corr-graph.png create mode 100644 docs/wiki/images/corr-trend.png create mode 100644 docs/wiki/images/monitor-graph.png diff --git a/docs/wiki/api-references/csp.profiler-API.md b/docs/wiki/api-references/csp.profiler-API.md index e0e5c0c36..114b3ca40 100644 --- a/docs/wiki/api-references/csp.profiler-API.md +++ b/docs/wiki/api-references/csp.profiler-API.md @@ -2,6 +2,7 @@ Users can simply run graphs under a `Profiler()` context to extract profiling information. The code snippet below runs a graph in profile mode and extracts the profiling data by calling `results()`. +Note that profiling can also be done in real-time with live updating visuals: see the [how-to](Profile-CSP-Code#profiling-a-real-time-cspgraph) guide here. ```python from csp import profiler diff --git a/docs/wiki/concepts/CSP-Graph.md b/docs/wiki/concepts/CSP-Graph.md index 03fadb7e8..5190e9ad0 100644 --- a/docs/wiki/concepts/CSP-Graph.md +++ b/docs/wiki/concepts/CSP-Graph.md @@ -8,60 +8,67 @@ ## Anatomy of a `csp.graph` -To reiterate, `csp.graph` methods are called in order to construct the graph and are only executed before the engine is run. -`csp.graph` methods don't do anything special, they are essentially regular python methods, but they can be defined to accept inputs and generate outputs similar to `csp.nodes`. -This is solely used for type checking. +`csp.graph` methods are called in order to construct the graph and are only executed before the engine is run. A graph is a collection of nodes and adapters which can either be executed as an argument to `csp.run` or composed into a larger graph. +The `csp.graph` decorator is only used for type validation and it is optional when creating a CSP program. A standard Python function without the decorator can also be passed as an argument to `csp.run` if type validation is not required. `csp.graph` methods can be created to encapsulate components of a graph, and can be called from other `csp.graph` methods in order to help facilitate graph building. Simple example: ```python @csp.graph -def calc_symbol_pnl(symbol: str, trades: ts[Trade]) -> ts[float]: - # sub-graph code needed to compute pnl for given symbol and symbol's trades - # sub-graph can subscribe to market data for the symbol as needed - ... +def calc_user_time(session_data: ts[UserSession]) -> ts[float]: + # sub-graph code needed to compute the time a user spends on a website + session_time = session_data.logout_time - session_data.login_time + time_online = csp.stats.sum(session_time) + return time_online @csp.graph -def calc_portfolio_pnl(symbols: [str]) -> ts[float]: - symbol_pnl = [] - for symbol in symbols: - symbol_trades = trade_adapter.subscribe(symbol) - symbol_pnl.append(calc_symbol_pnl(symbol, symbol_trades)) +def calc_site_traffic(users: List[str]) -> ts[float]: + user_time = [] + for user in users: + user_sessions = get_session(user) + user_time.append(calc_user_time(user_sessions)) - return csp.sum(symbol_pnl) + return csp.sum(user_time) ``` -In this simple example we have a `csp.graph` component `calc_symbol_pnl` which encapsulates computing pnl for a single symbol. -`calc_portfolio_pnl` is a graph that computes portfolio level pnl, it invokes the symbol-level pnl calc for every symbol, then sums up the results for the portfolio level pnl. +In this simple example we compute the total time all users spend on a website. We have a `csp.graph` subcomponent `calc_user_time` which computes the time a single user spends on the site throughout the run. +Then, in `calc_site_traffic` we compute the total user traffic by creating the user-level subgraph for each account and aggregating the results. -## Graph Propagation and Single-dispatch +## Graph Propagation and Single-Dispatch -The CSP graph propagation algorithm ensures that all nodes are executed *once* per engine cycle, and in the correct order. -Correct order means, that all input dependencies of a given node are guaranteed to have been evaluated before a given node is executed. -Take this graph for example: +The CSP graph propagation algorithm ensures that all nodes are executed *after* any of their dependencies on a given engine cycle. + +> \[!IMPORTANT\] +> An *engine cycle* refers to a single execution of a CSP graph. There can be multiple engine cycles at the same *timestamp*; for example, a single data source may have two events both at `2020-01-01 00:00:00`. These events will be executed in two *cycles* that both occur at the same timestamp. Another case where multiple cycles can occur is [csp.feedback](Add-Cycles-in-Graphs). + +For example, consider the graph below: ![359407953](https://github.com/Point72/csp/assets/3105306/d9416353-6755-4e37-8467-01da516499cf) -On a given cycle lets say the `bid` input ticks. -The CSP engine will ensure that **`mid`** is executed, followed by **`spread`** and only once **`spread`**'s output is updated will **`quote`** be called. -When **`quote`** executes it will have the latest values of the `mid` and `spread` calc for this cycle. +Individuals nodes are executed in *rank order* where the rank of a node is defined as the longest path between the node and an input adapter. The "mid" node is at rank 1, while "spread" is at rank 2 and "quote" is rank 3. Therefore, if "bid" ticks on a given engine cycle then "mid" will be executed before "spread" and "quote". Note that the order of node execution *within* a rank is undefined, and users should never rely on the execution order of nodes at the same rank. ## Graph Pruning -One should note a subtle optimization technique in CSP graphs. -Any part of a graph that is created at graph building time, but is NOT connected to any output nodes, will be pruned from the graph and will not exist during runtime. +Any node in a graph that is not connected to an output will be pruned from the graph and will not exist during runtime. An output is defined as either an output adapter or a `csp.node` without any outputs of its own. -The idea here is that we can avoid doing work if it doesn't result in any output being generated. -In general its best practice for all `csp.nodes` to be \***side-effect free**, in other words they shouldn't mutate any state outside of the node. -Assuming all nodes are side-effect free, pruning the graph would not have any noticeable effects. +Pruning is an optimization which avoids executing nodes whose result will be discarded. +As a result, it's best practice for any `csp.node` to be \***side-effect free**; they shouldn't mutate any state outside of the node. + +## Executing a Graph + +Graphs can be executed using the `csp.run` function. Execution takes place in either real-time or historical mode (see [Execution Modes](Execution-Modes)) depending on the `realtime` argument. Graph execution begin at a `starttime` and ends at an `endtime`; the `endtime` argument can either be a `datetime` which is past the start *or* a `timedelta` which is the duration of the run. For example, if we wish to run our `calc_site_traffic` graph over one week of historical data we can execute it with: + +```python +csp.run(calc_site_traffic, users=['alice', 'bob'], starttime=start, endtime=timedelta(weeks=1), realtime=False) +``` ## Collecting Graph Outputs -If the `csp.graph` passed to `csp.run` has outputs, the full timeseries will be returned from `csp.run` like so: +There are multiple methods of getting in-process outputs after executing a `csp.graph`. If the graph returns one or more time-series, the full history of those values will be returned from `csp.run`. -**outputs example** +**return example** ```python import csp @@ -69,46 +76,45 @@ from datetime import datetime, timedelta @csp.graph def my_graph() -> ts[int]: - return csp.merge(csp.const(1), csp.const(2, timedelta(seconds=1))) + return csp.merge(csp.const(1), csp.const(2, delay=timedelta(seconds=1))) -if __name__ == '__main__': - res = csp.run(my_graph, starttime=datetime(2021,11,8)) - print(res) +res = csp.run(my_graph, starttime=datetime(2021,11,8)) ``` -result: +res: ```raw {0: [(datetime.datetime(2021, 11, 8, 0, 0), 1), (datetime.datetime(2021, 11, 8, 0, 0, 1), 2)]} ``` -Note that the result is a list of `(datetime, value)` tuples. +Note that the result is a list of `(time, value)` tuples. You can have the result returned as two separate NumPy arrays, one for the times and one for the values, by setting `output_numpy=True` in the `run` call. -You can also use [csp.add_graph_output](Base-Adapters-API#cspadd_graph_output) to add outputs. -These do not need to be in the top-level graph called directly from `csp.run`. +```python +res = csp.run(my_graph, starttime=datetime(2021,11,8), output_numpy=True) +``` + +res: -This gives the same result: +```raw +{0: (array(['2021-11-08T00:00:00.000000000', '2021-11-08T00:00:01.000000000'], dtype='datetime64[ns]'), array([1, 2], dtype=int64))} +``` + +You can also use [csp.add_graph_output](Base-Adapters-API#cspadd_graph_output) to add outputs. +These do not need to be in the top-level graph called directly from `csp.run`. Users can also specify the amount of history they want stored in the output using the `tick_count` and `tick_history` arguments to `add_graph_output`. For example, if only the last value needs to be stored set `tick_count=1`. **add_graph_output example** ```python @csp.graph def my_graph(): - csp.add_graph_output('a', csp.merge(csp.const(1), csp.const(2, timedelta(seconds=1)))) -``` + same_thing = csp.merge(csp.const(1), csp.const(2, delay=timedelta(seconds=1))) + csp.add_graph_output('my_name', same_thing) -In addition to python outputs like above, you can set the optional `csp.run` argument `output_numpy` to `True` to get outputs as numpy arrays: - -**numpy outputs** - -```python -result = csp.run(my_graph, starttime=datetime(2021,11,8), output_numpy=True) +res = csp.run(my_graph, starttime=datetime(2021,11,8)) ``` -result: +res: ```raw -{0: (array(['2021-11-08T00:00:00.000000000', '2021-11-08T00:00:01.000000000'], dtype='datetime64[ns]'), array([1, 2], dtype=int64))} +{'my_name': [(datetime.datetime(2021, 11, 8, 0, 0), 1), (datetime.datetime(2021, 11, 8, 0, 0, 1), 2)]} ``` - -Note that the result there is a tuple per output, containing two numpy arrays, one with the datetimes and one with the values. diff --git a/docs/wiki/concepts/CSP-Node.md b/docs/wiki/concepts/CSP-Node.md index bf72fc325..18292a133 100644 --- a/docs/wiki/concepts/CSP-Node.md +++ b/docs/wiki/concepts/CSP-Node.md @@ -3,7 +3,7 @@ - [Table of Contents](#table-of-contents) - [Anatomy of a `csp.node`](#anatomy-of-a-cspnode) - [Basket inputs](#basket-inputs) -- [**Node Outputs**](#node-outputs) +- [Node Outputs](#node-outputs) - [Basket Outputs](#basket-outputs) - [Generic Types](#generic-types) @@ -21,7 +21,7 @@ They may (or may not) generate an output as a result of an input tick. ```python from datetime import timedelta -@csp.node # 1 +@csp.node(name='my_node') # 1 def demo_node(n: int, xs: ts[float], ys: ts[float]) -> ts[float]: # 2 with csp.alarms(): # 3 # Define an alarm time-series of type bool # 4 @@ -52,7 +52,7 @@ def demo_node(n: int, xs: ts[float], ys: ts[float]) -> ts[float]: # 2 Lets review line by line -1\) Every CSP node must start with the **`@csp.node`** decorator +1\) Every CSP node must start with the **`@csp.node`** decorator. The name of the node will be the name of the function, unless a `name` argument is provided. The name is used when visualizing a graph with `csp.show_graph` or profiling with CSP's builtin [`profiler`](#Profile-csp-code). 2\) CSP nodes are fully typed and type-checking is strictly enforced. All arguments must be typed, as well as all outputs. @@ -269,3 +269,6 @@ This allows us to pass in a `ts[int]` for example, and get a `ts[int]` as an out `const` takes value as an *instance* of type `T`, and returns a timeseries of type `T`. So we can call `const(5)` and get a `ts[int]` output, or `const('hello!')` and get a `ts[str]` output, etc... + +If a value is provided rather than an explicit type argument (for example, to `const`) then CSP resolves the type using internal logic. In some cases, it may be easier to override the automatic type inference. +Users can force a type variable to be a specific value with the `.using` function. For example, `csp.const(1)` will be resolved to a `ts[int]`; if you want to instead force the type to be `float`, do `csp.const.using(T=float)(1)`. diff --git a/docs/wiki/get-started/First-Steps.md b/docs/wiki/get-started/First-Steps.md index 5cdf65fba..224e22c26 100644 --- a/docs/wiki/get-started/First-Steps.md +++ b/docs/wiki/get-started/First-Steps.md @@ -1,20 +1,16 @@ -csp is a graph-based stream processing library, where you create directed graphs for real-time event streaming workflows. -In this introductory tutorial, you will write a csp program to calculate the Bid-Ask Spread for specified `bid` and `ask` values. - -> \[!TIP\] -> The bid–ask spread is the difference between the prices quoted for an immediate sale (ask) and an immediate purchase (bid) for stocks, futures contracts, options, or currency pairs in some auction scenario. -> ~ [Bid–ask spread on Wikipedia](https://en.wikipedia.org/wiki/Bid%E2%80%93ask_spread) +`csp` is a stream processing library that integrates real-time and historical playback workflows. Users compose a directed acyclic graph (DAG) of transformations and run them as a single pipeline with multiple data sources. +In this introductory tutorial, you will write a basic `csp` program to monitor production deployments. ## Introduction to real-time event stream processing -Real-time data is continuously collected or updated data like IT log monitorings or weather recordings. Stream processing is a the practice of working with or analyzing this data in real time. Streaming applications are driven by updates or changes to the input values. In csp, you refer to the input changes as "tick"s, and write the analysis workflow as a directed graph. +Real-time data is continuously updated in a stream of *events* that occur at unpredictable times. Stream processors handle these events and analyze their data so that underlying insights can be achieved in real-time. Each application is driven by updates to the input source values which propagate down the data pipeline. In `csp`, we refer to the input changes as "ticks" and write the analysis workflow as a directed graph. -csp programs are written in a functional-style, and consist of: +`csp` programs are written in a functional-style, and consist of: - runtime components in the form of `csp.node` methods, and -- graph-building components in the form of `csp.graph` components. +- graph-building components in the form of `csp.graph` methods. -## Imports +## Imports and time series ```python from datetime import datetime, timedelta @@ -23,84 +19,78 @@ import csp from csp import ts ``` -Data streams are often expressed as Time Series, and csp defines a high-level `ts` type that denotes a Time Series input. Most csp computation nodes require Time Series inputs. +`csp` defines a high-level `ts` type that denotes a time series input. The `ts` is to `csp` as the `Series` is to `pandas` or the `array` is to `numpy`: it is the fundamental data unit. A time series is a single stream of typed values. Whenever the stream is updated, any *consumer* of that data is invoked. Consumers are nodes or output adapters that ingest time series data. + +When you access a time series within a *node*, you access the *last value* of the time series. You can also store a fixed or variable sized history (see [CSP Node](CSP-Node)) for any input time series. +When you access a time series within a *graph*, you access the *edge* of the time series. This is simply the type, input and output definition of the data; it is used for building the graph at startup and ensuring type validation. -## Create a `csp.node` to calculate spread +## Create a `csp.node` to perform regex matching -`csp.node`s are the computational building-blocks of a csp program. You can use the `@csp.node` decorator to create a node that calculates the bid-ask spread. +The computational building blocks of any `csp` program are the nodes. You can use the `@csp.node` decorator to create a node that matches regular expressions. This will be useful for analyzing logfiles generated by our production deployments. ```python +import re + @csp.node -def spread(bid: ts[float], ask: ts[float]) -> ts[float]: - if csp.ticked(bid, ask) and csp.valid(bid, ask): - return ask - bid +def regex_match(log_line: ts[str], regex: str) -> ts[bool]: + if re.match(regex, log_line): + return True ``` -The `bid` and `ask` values are expected to be Time Series values. +The `regex_match` ingests a time series of strings which are the lines of our logs, and matches them against the expression "regex". The node returns a time series of Booleans. If the expressions match, then we output True; if they don't, then we don't output a value at all. This stops any downstream consumers from executing. > \[!IMPORTANT\] > csp nodes are strictly typed, and the type is enforced by the C++ engine. -This node needs to be executed each time the `ask` and `bid` values change, so we use the following built-in nodes: +The node will be invoked whenever the value of `log_line` is updated. Since we have a single input, we do not need to check whether `log_line` has ticked or if its valid. If there are multiple `ts` inputs in a `csp.node`, it is a good practice to check that each input is valid before accessing its value. -- `csp.valid` - To ensure the values have ticked at least once, where a "tick" refers to any change in the input -- `csp.ticked(bid, ask)` - to check if ask OR bid have ticked since we last checked - -csp have several helpful nodes for common computations. Check out the API Reference documentation pages to learn more. +`csp` has an extensive set of pre-written nodes for common computations. Check out the API Reference documentation pages to learn more. ## Create the graph -Next, you need a graph that defines the workflow, and you can use the `@csp.graph` decorator to create a graph. - -In the following graph, we define the example ask and bid values using [`csp.timer`](Base-Adapters-API#csptimer) and [`csp.count`](Base-Nodes-API#cspcount) and calculate the spread. - -`csp.timer` creates a repeating edge that **ticks** at the specified interval with the specified value (set to `True` here). `csp.count` continuously counts the number of ticks. +Next, we will create a `csp.graph` that analyzes the log messages from our deployment. For this example, we will use simulated log messages from a [`csp.curve`](Base-Adapters-API#cspcurve). Graph components are only executed once during application startup to construct the graph. Once the graph is constructed, `csp.graph` code is no longer needed. ```python +start = datetime(2020,1,1) + @csp.graph -def my_graph(): - bid = csp.count(csp.timer(timedelta(seconds=2.5), True)) - ask = csp.count(csp.timer(timedelta(seconds=1), True)) - s = spread(bid, ask) - - csp.print("bid", bid) - csp.print("ask", ask) - csp.print("spread", s) +def monitor_deployment(): + log_msgs = csp.curve(typ=str, data=[ + (start, 'WARNING: Load is heavy @ 90%'), + (start + timedelta(minutes=1), 'INFO: New connection on port 42'), + (start + timedelta(minutes=4), 'WARNING: Load is heavy @ 95%'), + (start + timedelta(minutes=6), 'INFO: New connection on port 43'), + (start + timedelta(minutes=9), 'CRITICAL: Overloaded, cannot connect new users!'), + ]) + + load_warnings = csp.count(regex_match(log_msgs, r'.*WARNING.*Load.*')) + new_connections = csp.count(regex_match(log_msgs, r'.*INFO.*New connection.*')) + + csp.print("load_warnings", load_warnings) + csp.print("new_connections", new_connections) ``` -`csp.graph` components are only executed once, during application startup to construct the graph. Once the graph is constructed, `csp.graph` code is no longer needed. - -During runtime, only the inputs, `csp.node`s, and outputs will be active as data flows through the graph. The graph run is driven by input **ticks**. - -[csp.const](Base-Adapters-API#cspconst) - -> \[!TIP\] -> You can also create csp-friendly constant time series values with [csp.const](Base-Adapters-API#cspconst). +In this graph, we count the number of load-related warnings as well as the number of new connections. ## Run the program -`csp.run` is the entry point to the graph, and you can define a particular start time and optionally an end time. +To execute a `csp` application we use the `run` function. Each run starts at a `starttime` and ends at an `endtime`. For the example above, we can run the graph using: ```python -if __name__ == '__main__': - csp.run(my_graph, starttime=datetime(2020, 3, 1), endtime=timedelta(seconds=10)) +csp.run(monitor_deployment, starttime=start, endtime=timedelta(minutes=10)) ``` The program will produce the following: ```python-console -2020-03-01 00:00:01 ask:2.0 -2020-03-01 00:00:02 ask:4.0 -2020-03-01 00:00:02.500000 bid:2.0 -2020-03-01 00:00:02.500000 spread:2.0 -2020-03-01 00:00:03 ask:6.0 -2020-03-01 00:00:03 spread:4.0 -... -2020-03-01 00:00:10 bid:8.0 -2020-03-01 00:00:10 ask:20.0 -2020-03-01 00:00:10 spread:12.0 +2020-01-01 00:00:00 load_warnings:1 +2020-01-01 00:01:00 new_connections:1 +2020-01-01 00:04:00 load_warnings:2 +2020-01-01 00:06:00 new_connections:2 ``` +Take a moment to reason with this output. Each `csp.count` node is only invoked when its `regex_match` ticks a value, and each `regex_match` node only ticks a value when the match is valid. + ## Visualize To visualize this graph, you can [install `graphviz`](https://graphviz.readthedocs.io/en/stable/manual.html) and use `csp.show_graph` to view and save the image. @@ -109,8 +99,8 @@ To visualize this graph, you can [install `graphviz`](https://graphviz.readthedo csp.show_graph(my_graph, graph_filename="tmp.png") ``` -![Output generated by show_graph](images/ask-bid-graph.png) +![Output generated by show_graph](images/monitor-graph.png) -In the above graph, the blue arrows (`csp.timer`) indicate inputs and the red arrows (`print`) indicate outputs. The operations, in our case `count`, `cast_int_to_float`, and `spread`, are denoted by rectangles. `cast_int_to_float` is an implicit operation because `csp.count` returns integer values. +The blue arrows (`csp.curve`) indicate inputs and the red arrows (`csp.print`) indicate outputs. The nodes, in our case `regex_match` and `count`, are denoted by rectangles. Check out the expanded and complete example: [e3_show_graph.py](https://github.com/Point72/csp/blob/main/examples/01_basics/e3_show_graph.py). diff --git a/docs/wiki/get-started/IO-with-Adapters.md b/docs/wiki/get-started/IO-with-Adapters.md index 31fc95351..7065d89b1 100644 --- a/docs/wiki/get-started/IO-with-Adapters.md +++ b/docs/wiki/get-started/IO-with-Adapters.md @@ -1,17 +1,17 @@ -In [First Steps](First-Steps) and [More with csp](More-with-CSP) you created example/sample data for the streaming workflows. In real workflows, you use data stored in particular formats and storage spaces, that can be accessed directly or through an API. +In [First Steps](First-Steps) and [More with CSP](More-with-CSP) we used toy data for the streaming workflows. In real workflows, we need to access data stored in particular storage formats. To bring data into or out of a `csp` graph, we use **adapters**. -csp has [several built-in "adapters" to access certain types of data](Input-Output-Adapters-API), including Kafka and Parquet. csp requires friendly (Time Series) data types, and the I/O adapters form the interface between the data types. You can also write your own adapters for other data types, check the corresponding how-to guides for more details. +`csp` has [several built-in adapters to access certain types of data](Input-Output-Adapters-API) such as Kafka and Parquet. You can also write your own adapters for any other data format; for reference, see the various "How-to" guides for [historical](Write-Historical-Input-Adapters), [real-time](Write-Realtime-Input-Adapters) and [output](Write-Output-Adapters) adapters. I/O adapters form the interface between external data and the time series format used in `csp`. -In this tutorial, you write to, and read from, Parquet files on the local file system. +In this tutorial, you write to and read from Parquet files on the local file system. -csp has the `ParquetWriter` and `ParquetReader` adapters to stream data to and from Parquet files. Check out the complete [API in the Reference documentation](https://github.com/Point72/csp/wiki/Input-Output-Adapters-API#parquet). +`csp` has the `ParquetWriter` and `ParquetReader` adapters to stream data to and from Parquet files. Check out the complete [API in the Reference documentation](https://github.com/Point72/csp/wiki/Input-Output-Adapters-API#parquet). > \[!IMPORTANT\] -> csp can handle historical and real-time data, and the csp program remains similar in both cases. +> `csp` graphs can process historical *and* real-time data with little to no changes in the application code. -## Example +## Streaming a csp.Struct -You start with an Example `csp.Struct` data type which will be streamed into a Parquet file. +A `csp.Struct` is a basic form of structured data in `csp` where each field can be accessed as its own time series. It is analogous to a dataclass in Python, and its fields must be type annotated. We will store some example data in a custom struct called `Example` and then stream the struct to a Parquet file. ```python from csp.adapters.parquet import ParquetOutputConfig, ParquetWriter, ParquetReader @@ -23,13 +23,11 @@ class Example(csp.Struct): ## Write to a Parquet file -In a graph, create some sample values for `Example` and use `ParquetWriter` to stream it to a Parquet file. +In a graph, create some sample values for `Example` and use `ParquetWriter` to stream to a Parquet file. -1. The `timestamp_column_name` is how csp preserves the timestamps. Since you need to read this file back into csp, you can provide a column name. If this was the final output and the time stamp information is not required, you can provide `None`. - -1. You can provide optional configurations to `config` in the `ParquetOutputConfig` format (which can set `allow_overwrite`, , `batch_size`, `compression`, `write_arrow_binary`). - -1. Use `publish_struct` to publish (write) the data as Time Series. +1. The `timestamp_column_name` is how `csp` preserves the timestamps on each event. If the timestamp information is not required, you can set the column name argument to `None`. +1. You can provide optional configurations in the `ParquetOutputConfig` format which can set `allow_overwrite`, `batch_size`, `compression`, and `write_arrow_binary`. +1. We use `publish_struct` to publish (write) the time series data to disk. ```python @csp.graph @@ -52,7 +50,7 @@ def write_struct(file_name: str): ## Read from Parquet file -You can use `ParquetReader` with a `time_column`, and read all the `Example` rows with `subscribe_all`. +You can use `ParquetReader` with a `time_column` to read back the data. ```python @csp.graph diff --git a/docs/wiki/get-started/More-with-CSP.md b/docs/wiki/get-started/More-with-CSP.md index 690586d27..fbd9ae7a9 100644 --- a/docs/wiki/get-started/More-with-CSP.md +++ b/docs/wiki/get-started/More-with-CSP.md @@ -1,141 +1,111 @@ -csp offers several built-in generic, mathematical, and statistical nodes that are often required in streaming workflows. This allows you to write applications quickly, and update and expand them as required by including new nodes. +Nodes in `csp` have many more complex features than we saw in the [First Steps](first-steps) example. These include state, alarms and start/stop execution blocks. Also, the `csp` library has an extensive set of pre-written nodes that are optimized in C++. You can leverage these nodes to quickly build high-performing applications. -In this tutorial, you will calculate the [volume weighted average price (VWAP)](https://www.investopedia.com/terms/v/vwap.asp) and the profit and loss (PnL) of the trade, on a stream of trades. Check out the complete example: [trade profit-and-loss example](examples/01_basics/e4_trade_pnl.py) +In this tutorial, you will create a Poisson counter that counts the number of events in a [Poisson process](https://en.wikipedia.org/wiki/Poisson_point_process). We will then look at the correlation between two independent Poisson processes by leveraging nodes in `baselib` and `stats`. -## Compound inputs with `csp.Struct` +## Building our Poisson counter -A Trade consists of multiple parts: price of a share, quantity of shares, and indication of a buying or a selling transaction. +A Poisson point process has events which are exponentially distributed across time. The average delay between events is controlled by the rate parameter "rate". In the `poisson_counter` node below, we use the following useful node features: -`struct` is a useful data type for this type of information. In csp, you can use [`csp.Struct`](csp.Struct-API), a higher-level data type that can be defined with type-annotated values. +1. `csp.state`: we keep a *state* variable in the node which is the count of events thus far. A state variable can be thought of as a "member" of the node. +1. `csp.alarms`: we schedule an *alarm* to simulate each event. An alarm is an internal time series which feeds back to the same node. +1. `csp.start`: we schedule the first alarm at *start* time, which is when the graph begins execution. There is also a *stop* block available in nodes which runs when the graph stops. + +We also turn off memoization for the node by passing `memoize=False`. This means that when we create two `poisson_counter` nodes with the same "rate" argument we get two different random time series. ```python -class Trade(csp.Struct): - price: float - qty: int - buy: bool +import csp +from csp import ts +from datetime import timedelta +import numpy as np + +@csp.node(memoize=False) +def poisson_counter(rate: float) -> ts[int]: + with csp.alarms(): + event = csp.alarm(int) + with csp.state(): + s_count = 0 + with csp.start(): + delay = np.random.exponential(rate) + csp.schedule_alarm(event, timedelta(seconds=delay), True) + + if csp.ticked(event): + s_count += 1 + next_delay = np.random.exponential(rate) + csp.schedule_alarm(event, timedelta(seconds=next_delay), True) + return s_count ``` -## Build computing nodes - -To calculate volume-weighted averages, you need the cumulative sum of previous trade prices and quantities. Hence, your csp node needs to store stateful information. You can use \[`csp.state`\] to declare stateful variables that bound to the node. - -A csp node can return multiple named outputs, denoted as `csp.Outputs` type, created using the `csp.output` function. The individual return values can be accessed with dot notation. +We can run the node using `csp.run` as follows: ```python -@csp.node -def vwap(trade: ts[Trade]) -> csp.Outputs(vwap=ts[float], qty=ts[int]): - with csp.state(): - s_cum_notional = 0.0 - s_cum_qty = 0 +from datetime import datetime - if csp.ticked(trade): - s_cum_notional += trade.price * trade.qty - s_cum_qty += trade.qty - - csp.output(vwap=s_cum_notional / s_cum_qty, qty=s_cum_qty) +res = csp.run(poisson_counter, rate=2.0, starttime=datetime.utcnow(), endtime=timedelta(seconds=10), realtime=False) +print(f'Final count: {res[0][-1][1]}') ``` -```python -@csp.node -def calc_pnl(vwap_trade: ts[Trade], mark_price: ts[float]) -> ts[float]: - if csp.ticked(vwap_trade, mark_price) and csp.valid(vwap_trade, mark_price): - if vwap_trade.buy: - pnl = (mark_price - vwap_trade.price) * vwap_trade.qty - else: - pnl = (vwap_trade.price - mark_price) * vwap_trade.qty - - return pnl +Since the rate is set to 2.0, we would expect a new event approximately every 2.0 seconds. Therefore, the average of multiple runs should converge to 5 events. Running the counter multiple times, we get: + +```raw +Final count: 6 +Final count: 1 +Final count: 6 +Final count: 5 +Final count: 5 +Final count: 2 +Final count: 9 +... ``` -## Create workflow graph +## Correlation between two Poisson processes -To create example `ask`, `bid`, and `trades` values, you can use [`csp.curve`](Base-Adapters-API#cspcurve). -This commonly-used type in csp converts a list of (non-CSP) data into a ticking, csp-friendly inputs. +We can use a combination of pre-written nodes from `baselib` and `stats` to calculate the correlation of two Poisson point processes in 1-minute buckets. Even though both processes have the same rate they will be fully independent, so we expect the correlation to converge to zero. + +We will first compute the number of events in each 1-minute period by using the (`csp.diff`)\[Base-Nodes-API#cspdiff\] and (`csp.sample`)\[Base-Nodes-API#cspsample\] functions. `diff` gives the difference between the value of a time series at the current time and some time in the past. `sample` will get the value of a time series whenever some other time series ticks. We will also use a (`csp.timer`)\[Base-Adapters-API#csptimer\] so that we sample the values every minute. ```python @csp.graph -def my_graph(): - st = datetime(2020, 1, 1) - - # Dummy bid/ask trade inputs - bid = csp.curve( - float, - [(st + timedelta(seconds=0.5), 99.0), (st + timedelta(seconds=1.5), 99.1), (st + timedelta(seconds=5), 99.2)], - ) - - ask = csp.curve( - float, - [ - (st + timedelta(seconds=0.6), 99.1), - (st + timedelta(seconds=1.3), 99.2), - (st + timedelta(seconds=4.2), 99.25), - ], - ) - - trades = csp.curve( - Trade, - [ - (st + timedelta(seconds=1), Trade(price=100.0, qty=50, buy=True)), - (st + timedelta(seconds=2), Trade(price=101.5, qty=500, buy=False)), - (st + timedelta(seconds=3), Trade(price=100.50, qty=100, buy=True)), - (st + timedelta(seconds=4), Trade(price=101.2, qty=500, buy=False)), - (st + timedelta(seconds=5), Trade(price=101.3, qty=500, buy=False)), - (st + timedelta(seconds=6), Trade(price=101.4, qty=500, buy=True)), - ], - ) +def events_per_minute_bucket(poisson_counter: ts[int]) -> ts[int]: + minute_timer = csp.timer(interval=timedelta(minutes=1), value=True) + sampled_event_count = csp.sample(trigger=minute_timer, x=poisson_counter) + events_per_minute = csp.diff(sampled_event_count, lag=timedelta(minutes=1)) + return events_per_minute ``` -The next step is to separate the buying and selling transactions that are captured in `Trade.buy` and calculate the VWAP. You can use the [csp.split](Base-Nodes-API#cspsplit) function for this. It splits input based on a boolean flag. - -> \[!TIP\] -> To perform the opposite operation of a split you can use [csp.merge](Base-Nodes-API#cspmerge). +We can call this subgraph with two different Poisson processes of `rate=1.0` to generate our 1-minute event counts. We can then find the correlation between the two series using `csp.stats.corr`. ```python -buysell = csp.split(trades.buy, trades) -buy_trades = buysell.true -sell_trades = buysell.false +from csp import stats -buy_vwap = vwap(buy_trades) -sell_vwap = vwap(sell_trades) +@csp.graph +def corr_graph() -> ts[float]: + # Define two Poisson point processes + process_A = poisson_counter(rate=1.0) + process_B = poisson_counter(rate=1.0) + + # Get the per minute event counts + counts_A = events_per_minute_bucket(process_A) + counts_B = events_per_minute_bucket(process_B) + + # Compute correlation between two independent processes + corr = csp.stats.corr(counts_A, counts_B) + return corr ``` -Finally, you need to calculate the profit-and-loss using the VWAPs of trades. You can create new "Trade" `Struct`s with using [`fromts`](csp.Struct-API#available-methods) and perform the computation: - -```python -buy_vwap = Trade.fromts(price=buy_vwap.vwap, qty=buy_vwap.qty, buy=buy_trades.buy) -sell_vwap = Trade.fromts(price=sell_vwap.vwap, qty=sell_vwap.qty, buy=sell_trades.buy) - -mid = (bid + ask) / 2 -buy_pnl = calc_pnl(buy_vwap, mid) -sell_pnl = calc_pnl(sell_vwap, mid) - -pnl = buy_pnl + sell_pnl +## Running the graph and analyzing results - csp.print("buys", buy_trades) -csp.print("sells", sell_trades) -csp.print("buy_vwap", buy_vwap) -csp.print("sell_vwap", sell_vwap) +We can run the above `corr_graph` for 2500 minutes of simulated time and analyze the correlation. Using: -csp.print("mid", mid) -csp.print("buy_pnl", buy_pnl) -csp.print("sell_pnl", sell_pnl) -csp.print("pnl", pnl) +```python +csp.run(corr_graph, starttime=datetime(2020,1,1), endtime=timedelta(minutes=2500), realtime=False) ``` -Execute the program and generate an image of the graph with: - -```python -def main(): - start = datetime(2020, 1, 1) - csp.run(my_graph, starttime=start, endtime=timedelta(seconds=20)) - csp.show_graph(my_graph, graph_filename="tmp.png") +and extracting the correlation values, we see that the correlation converges to near zero as we expected. -if __name__ == "__main__": - main() -``` +![Correlation graph](images/corr-trend.png) -As expected, the graph for this workflow show the split of buy & sell Trades, calculation of VWAP for each followed by using the VWAP-Stucts in profit-and-loss calculations: +## Visualization -![Output of show_graph](images/pnl-graph.png) +We can visualize the graph used to calculate our autocorrelation using the `show_graph` utility. Take a moment and match each node to where it lies in the `corr_graph` code. Note that many of the nodes shown are subcomponents of the library functions we used. -Check out the [trade profit-and-loss example](https://github.com/Point72/csp/blob/main/examples/01_basics/e4_trade_pnl.py) to learn more. +![Output of show_graph](images/corr-graph.png) diff --git a/docs/wiki/images/corr-graph.png b/docs/wiki/images/corr-graph.png new file mode 100644 index 0000000000000000000000000000000000000000..6bf5c18946826eb72bc5051c6e2ddfbd0848e0bd GIT binary patch literal 63004 zcmd4(cRbep`v#6*N*P&6l1&KN5s?vPXUnGSSrQppm8fKvol&-mWE7FRA)}0pGLi~e z8D;O^an<|tc>KP9eEOo1OaImB@JhkH%)KV{eXEJ) z`?@F^8DeW+ldo)C_?lO9wo!rPW#&VZ;x|oA7pL!-s!xAu+YozeD^7wtAYP%?D$&#b z{)#`dw757(|My?*FF61I{{Cc)hWPU=6RlIHHilvp$D+6O>2T8Z^z^i|;n9>P#oBe5 z@q$p*bLY;*#l?B6k$5!Nmb$vS;+6P4A2Ay$;{Vp+j%#dc(x4hJG%_;s@DLu@x`7{? zQ?GF1U&Jf)>yH2L|K0hmuHr^cULGS0i8ppwe@e4( zoVX0NCmkF{o?jR;_nVy`?~II$oSK@F3miVpwyrbUmdSC{izlXG?#~}DZ|`5R;&Mln z@hkho0_pHCrSliomw$ixV%euQ-6JL;A<^T0Ni9lsyyhUnQAzdRrnbwUIC0`O>(Tf( z-}wau_V3^CF;JaAN6*1={@l6Zyu5ecJ%xmYLpE2OCcfDOuQ<$)eY6xYF*fe*=y;lw zV_$!3??aQ4;Dw33*Itbc)`iTCR$m;AzH)^GkL~%5z%|@{Uqw?>(^6#V_4Qqb`8vk< z&CX7_i$AG+JRho_^Lt_{L_eX$TZJAPTpRgDff5P6@*DuTrD$2>Nbrl*? z?Nl){tNJe9Li=^B>~qn3EaF®_W}jqO~V9+>?8{rlKhaza8vTwLkdH{nig8M~Fe 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 tpP~k12026=_+L`(|NO5Pme0}N$WBOyZu)`#F5? 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%0DHkj? zb$$GIzpV$07+UB$S?D>w({)<9@>%Agfcr*>eO-IQ+iB$EHHCoXZ*CzjZ705o(l}Ey zWZ+$Po;Nk5B)$a74mYtNJ97Zcb|0{H6=KmCr>Q&H}NVPJ@(#j4XZ6ekMOV0S7Xse2<|Lwi&Z(C7jurCDf#(O z_fB;c5GVN*`kkvS%bKsrjA&|J8%r3F^;)w^8};E-4SsroSTva&ya zFkp~Ye|$pGZu@HXGGj-y`AIN(Rl7l(#K`@iPWxD5lONh1@@wUamDt$7sk&M#)C`Dn@f)Af_!AyLIRa6; zKcB|P(ckXsM91Ff8nzk85l0$&k)c2b!m!)AIo!p(w6X_ z2ucywRNtbKddijnm871^`BJgm;F@Lra#B5KDlW$}q1|go^LcS;Nfu~VF_U0rF6*Ds z@M&h)k;tEKXzlr$u6{Q78#bV{6e^BA(`xg^rTpD&yWG)5OCGXMDIjr~2-`cm@(TW@ z={i|gf3AdIch)=WAf|t@nCcmw*HDMkwm6lk0dtaoVl{{TJ5c5B;%h^jz+MP@BmdX8` zAfoX!!QHQ^(c+h|w>yCwE&+U3R9~RKD`e*4*%%MJM8r!=jIHTt<_65`;N^Sy1$H|H zYO?#qYAkOFXiq$E_8%LgneG2^&&%i@KVRxN1`%6$aS`fnpG0<@TZaA-CLx!Xw{(cr z5iE-%wHRkb^(xmNucaWm=C;xwA2YS(-pSDy1)a&t8oSigdyNN$s%)@Q>m%pa zx}AM*k;3%?SS{rNO><{__Gj_#|BCAf9!^{QTQ^mgpcmq>GMU4jJtEIzIlHA`tEypB25QacVFO@k_`p585i(E z`?==pQTAetQX&aC*{mhzp+4D^rhp2I{^r}8OF)|dhkf*@rN5u^(W6ZN+Z%(D_b64> z)dH-nMa|i1QM+NOsi^=i0zG$5aNp}$fu8_Bkow3t4E7EWZ6Z20)(Ho`21;NDFCMIP z=e;fT+-5-;85sx!0z6C6TV;HOA*X6MnVIuvMEg?r&wZp>Io~@7 zrFk@^Xo#gyx-~HY!B$$Dq7f+CmNRuQKz^3)9>n+WXQ>sG7&U#3i*w%mR{#)`&&5Wb zkEs8AOMop)B#lTtkgV+V>eLF*2AI3Ue{D}xtQFVH^0+;Sb{##ox4yQu9zPZp6QqRy zYHgX06VFg@0|*NsuIr0qKs-<#Pj?Ij9soiQNLij*L1Sa%ze{ZJe>R#+RL|_M0P9~` zTm-N{PoJDFr$PaRK0AABbMsCsZ+XYh@N#2Yj1$?-HE%&qoz%H?d*BhEGi`Y>$S?ne z`w*|HW@T}a=;7T1H?zE)=h?F)<>0Weu*pe1CZ;?fsFW9Q`J6chhz~f~Y>gHJm2C=~ z4d6-}VhTZoq~5H(f0D_e5M0z%dB9FEY$oG-#$zY;X#U+6zMG9y0hBO2JY0!Notb2< zKSM=c9t$7e&CwAu0Se&ST8-nv@5i#AG_&y!+C{vAv%C8q$)#Xhl z-Pzt=)n1n*bLJ!JZDa}<9Kb`ho`>&%oDTMthli&lips*=oY!T20IU`W=!>!{yDxk% z_=I?Zif;kI^}RUKt+Lk4d&mKxL9wSe4H&23_IlUJ@i=*E0z)q24z`QRT`J+?;tGVc!k`Aga_GH zk&lETk=>jKAO^49-t691dq)K&$Nm6(qrtv4s8Do^$&G)mi?-7Skv9FmlLo^WRfIlSr`tqgYIO zy1Fl3yl~x}odJ*D-rkXsk@ohL&5*gm%ak`cDI_sOZCEk{0X zdS=ED=v#({;7e&~Y2cZEwhz$cDu2%)!r>eh@?>culB-ih2S?U}Spdl0=X}S;HG$7W zlXmxGz%l9xvj5LRO8ba!D&Eib_?_v+(S})Ba_d5+utXAJ_8$~m_%804iH(Eo%S*I2 zww%1YhWh%BjtK+PAasOg6EAK&|c1bnl)Icg*{3^ z`AkVkkz*(?E7L7C3GliBLXd~Ix4yo9gw!{%G+IHIFw^9)Fw88~KQ}z5>w|%5&fSUZ zz?A}021|mMmsg2S*$2~P5N^(O(>*;sEiK|8?m+RWtmKnCu6XIPJ^26v3cgcazu2u0 zaB%7mkAKLThvsV(wzai2`(6SS1Ncj0KoA9ig1iC*@c||p(9V$E6BQPU0Eo7?x8t_v zeE+VHs}?R*4w?uUf|Zq3TYC&>@};~s29GB#Yy3|3_hBt-hc6!X4P;4<{m@m{(D-L7 zQhck67X~kB!EM1Jg!RKLXqp80^pitIt6f z6XfLVTvSvpsg=8Hnt3i$Uw*e#q$1Rndi@+mktMh z_&{m@{&O6VGCMngL>dpI)$vj~K0b{Z0zkpuzI_Xv8<4qV;Zl?tB>&`um|zi|OTeiS z&A9!``qOr{v97#aZO!ZJRt!*tu!4UB&YhT$VA$;A`6q_Xu-@gh12HIQBl0a=N)i$u z1hJAa((c4@VBx{x5D2w8gTCe|%P7l&v^aSCf+MhiKzwnVNhv6Nyujh{Vt}FcKx}YU zarPL3GZZcHg=}{+REQp4)$(SZWzQn;&b7dcM?DRIT2Nxdyq@LrQ)Ip+S0!>WDOULK z^(*DcTV>@a4VE;Xx7e3zjB(*o-#|d{;x27%2?1r{_=BmbDd@96&{@eP51A-6MTG<9 zaC^M$F$;^r<K9JSAk!+|^;(a=@S?<)3$Ur@ z=%c|OLO74~^Tx!S!7F8SxUkxAmFw;+hpgJz6bIE3kwVAKMx)}=(TeJDmpYiIZ1gnEGZ#@JNxc2 zeQbWP`vjbglT*y+tn|cAV2lm~J;cV&PW7s?s%oS*!B%B^pg*eF^|7s3_nUH1+Q|1L zrNzr&DZ?X5Ca6g%XYFKBpWz+&U#L$Ar2s-}^=%!_Q$f{f_Bl`HHU~!PJ3BiOApFI| z#M}i1a6eR;N$%gjFE1|-RJoh0!~UsnNB|$?;}}8XTUlLAOiKExSEaCI3)D6U2-_xm zD3d2}^j0ohb3414={y`X6#P(gQ`7xEq20<&jLKeD%oMz+>Ps+hAb1zA#|sSLUr&SI zUKKU;WwQqW0He_&7lj!$a=HSJ3q(22>eBIB!=;FE;CbK+ovi_>O?eK;`Unu|@86e6 zWHGa`86fZBhax}ST-yAMb(*tU@I#tPf0$4T=MqxEYrrZNi7C_ z2Ppr=7seG&&7Ucu1ei?Mz6ZiDz}Wx|6?L>u_ga-mUYzbaSXp`ATzMYHPfr`v8I;(k z_ODSbTdIV%q%+Jr)n&^>DX6G$K7D$AbGa)UNp6~d;t!FxnDlN0MFm6M5;+RmwA|kv` zCM-ZTng}GqSYB9w&94t;1Ez2%5x2HZfZ2mW%nq>sj~~lUb-*?U<{Tyg0m6ChlR|Fc zj~|UrD<4fGtZb0*#1N|Qf%gb7?%gYrwXjxUAhJRdmgzjCrfzbWYX${GQ$u5UWu^Bk zfA_?MC(zlDAHba#5K=P;e+1ZF4vuEmt;7@BNyn&Ur&NG;-7LC0JDIq-%kuNrK|%rv z(C&OMHc_KRQXI!rWqg(TXTcG*Gx8UuX=1#BS&VAbp}siYg!Ips!0;X$&po!dafo2=>{9J~() z!2uv4MTl;#V^-7M%?vw7$Gv*jEeIH3*`=j>;O0eodOD~=b8{KgXm!A_gP~%CwF9#T zc#!kpSX{+`_p$}#@TqD$b9Z-e%^+RSCqJzd|NZlaVqyq9Dgn@r$P3fIQ~&0Q1oFF_ z-1 zJ-doZKVV5*xWg_{mf6>x_;{3j%uk&wQpJ)8YDC{vwKQ#Rc2tofvN#u&XVMCm}yzyk-UD& z3+H!2J|9CY`fD2UXi2<+`iNr?00Rby$0R0#@+T53@g9_R2zi-JKd9V8{616|J1sE@AN8!NgAq1R1&jJ?|(EAc{IFnaaSj7uy zXnbFoQ5g@;5jr{#Z}&SvmERoYxx0B~Igdp4tnEvD6~^ldJA3$PvCGEgA9qZ#EH3;L z_<=AP7z~D;I~4Owc&Hx`#{^}wd4ADbi|}Q!iHVE