TradingPipeline
Hello, how are you?
DocumenterVitepress.jl generates very good-looking output.
Live Reloading SAGA
- Live-reloading doesn't work as documented.
It's almost there, but not quite.
It can't serve the js and css assets.
However, it does live reload the HTML parts.
Holy fucking shit.
It is so hacky, but I made it work.
servedocs() starts a LiveSerever
then I run another LiveServer, but the two servers share state, and the config I give the second one overrides the first LiveServer.
Finally, I added a userscript to hack the websocket listener to make it wait a few seconds before reloading the page.
[2025-08-04 Mon 19:13] UPDATE: I made it less hacky after reading the source of LiveServer.servedocs and passing in a custom buildfoldername of "build/1" to match the new way of doing things.
'(testing 1 2 3)
include("makedev.jl")
# This runs a LiveSerever.
sd_pid = Threads.@spawn servedocs(foldername=pwd())
# This runs another LiveServer, but it also overrides the `dir` for the first one.
# The LiveServer is effectively a singleton.
ls_pid = Threads.@spawn LiveServer.serve(dir = "./build/1")
And then the UserScript to top it all off.
// ==UserScript==
// @name New script localhost
// @namespace Violentmonkey Scripts
// @match http://localhost:8000/*
// @grant unsafeWindow
// @version 1.0
// @author -
// @description 8/4/2025, 6:26:18 PM
// ==/UserScript==
unsafeWindow.ws_liveserver_M3sp9.onmessage = function(msg) {
if (msg.data === "update") {
console.log("update received");
ws_liveserver_M3sp9.close();
setTimeout(() => { console.log("after wait"); location.reload() }, 3000);
};
};
console.log("websocket delay hack added.")
Documentation for TradingPipeline.
TradingPipeline.simulate_sanity_check_failure_error
TradingPipeline.AbstractExchangeResponse
TradingPipeline.AbstractManualCommand
TechnicalIndicatorCharts.visualize
TradingPipeline.PNL.pnl
TradingPipeline.PNL.pnl
TradingPipeline.PNL.qty
TradingPipeline.PNL.qty
TradingPipeline.Stops.set_subject!
TradingPipeline.around
TradingPipeline.decide
TradingPipeline.load_strategy
TradingPipeline.load_strategy
TradingPipeline.percent_diff
TradingPipeline.report
TradingPipeline.simulate
TradingPipeline.PNL.@pnl
TradingPipeline.PNL.@pnls
TradingPipeline.simulate_sanity_check_failure_error Constant
simulate_sanity_check_failure_error
is a tuple filled with a lot of nothing values so that code that's @unpack'ing return values from simulate()
don't crash.
TradingPipeline.AbstractExchangeResponse Type
An AbstractExchangeResponse represents a message that was received from an ExchangeFillSubject. The most common is ExchangeFill which lets the StrategySubject know that after putting out an intent to open or close a position, the exchange has filled the order and the requested position change has occurred.
Example
julia> subtypes(TradingPipeline.AbstractExchangeResponse)
TradingPipeline.AbstractManualCommand Type
An AbstractManualCommand represents a manual intervention from a human to the StrategySubject.
Example
julia> subtypes(TradingPipeline.AbstractExchangeResponse)
TechnicalIndicatorCharts.visualize Method
visualize(
t::Tuple{TechnicalIndicatorCharts.Chart, ExchangeOperations.AbstractSession};
kwargs...
) -> LightweightCharts.LWCLayout
Let's see if I can visualize trades on top of a chart.
sourceTradingPipeline.around Method
around(
ts::Dates.DateTime,
df::DataFrames.AbstractDataFrame;
before,
after,
ts_field
) -> Any
Return a few rows before and after the given timestamp ts
in the DataFrame df
.
TradingPipeline.decide Method
decide(strategy::AbstractStrategy, state::HSM.AbstractHsmState)
-> Union{Nothing, TradeDecision.T}
The decide method takes the current strategy and the current state according to the state machine, and looks at the market data available to it to make a decision. Often, it decides to return nothing
, but if conditions as defined by the strategy are met, it could return an HSM.AbstractHsmEvent
which will cause the state machine to move to the next appropriate state.
There are decide methods for every state in the state machine.
sourceTradingPipeline.load_strategy Method
Initialize a long-only hma strategy.
- Looking for 330/440 crosses
TradingPipeline.percent_diff Method
percent_diff(a, b) -> Any
Return the percent difference between a
and b
.
TradingPipeline.report Method
report(session::XO.SimulatorSession) -> DataFrame
Return a list of trades that happened during the simulator session.
sourceTradingPipeline.simulate Method
simulate(
candle_observable,
strategy_type::Type{<:TradingPipeline.AbstractStrategy};
kwargs...
) -> Any
Run a strategy on the simulator using the given candle_observable
.
Return Values
A named tuple with the following keys will be returned: simulator_session
, hsm
, simultator_exchange_driver_subject
, fill_observable
, chart_subject
, strategy_subject
, simulator_session_actor
.
Example
julia> candle_observable = df_candles_observable(btcusd1m)
IterableObservable(Candle, Vector{Candle}, Rocket.AsapScheduler)
julia> @unpack simulator_session, chart_subject = simulate(candle_observable, HMAStrategy);
TradingPipeline.Stops.set_subject! Method
set_subject!(subject::Rocket.AbstractSubject)
Mutate the subject of all TP.Stops state instances. This is my workaround for state machines being singletons.
source