Skip to content

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)
julia
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.

javascript
// ==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 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.

source
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
julia> subtypes(TradingPipeline.AbstractExchangeResponse)
source
TradingPipeline.AbstractManualCommand Type

An AbstractManualCommand represents a manual intervention from a human to the StrategySubject.

Example

julia
julia> subtypes(TradingPipeline.AbstractExchangeResponse)
source
TechnicalIndicatorCharts.visualize Method
julia
visualize(
    t::Tuple{TechnicalIndicatorCharts.Chart, ExchangeOperations.AbstractSession};
    kwargs...
) -> LightweightCharts.LWCLayout

Let's see if I can visualize trades on top of a chart.

source
TradingPipeline.around Method
julia
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.

source
TradingPipeline.decide Method
julia
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.

source
TradingPipeline.load_strategy Method

Initialize a long-only simple golden cross strategy.

source
TradingPipeline.load_strategy Method

Initialize a long-only hma strategy.

  • Looking for 330/440 crosses
source
TradingPipeline.percent_diff Method
julia
percent_diff(a, b) -> Any

Return the percent difference between a and b.

source
TradingPipeline.report Method

report(session::XO.SimulatorSession) -> DataFrame

Return a list of trades that happened during the simulator session.

source
TradingPipeline.simulate Method
julia
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
julia> candle_observable = df_candles_observable(btcusd1m)
IterableObservable(Candle, Vector{Candle}, Rocket.AsapScheduler)

julia> @unpack simulator_session, chart_subject = simulate(candle_observable, HMAStrategy);
source
TradingPipeline.Stops.set_subject! Method
julia
set_subject!(subject::Rocket.AbstractSubject)

Mutate the subject of all TP.Stops state instances. This is my workaround for state machines being singletons.

source