dysonance / strategems.jl Goto Github PK
View Code? Open in Web Editor NEWQuantitative systematic trading strategy development and backtesting in Julia
License: Other
Quantitative systematic trading strategy development and backtesting in Julia
License: Other
Implement a Julia type, Order
(or AbstractOrder
from which more concrete order types could be children, like MarketOrder
, LimitOrder
, StopOrder
, etc.) for storing, processing, and manipulating orders.
This type should be able to interact with a Portfolio
object in a highly structured order queue processing pattern. In other words, when a Signal
/Rule
triggers some market action, it should be communicated through an Order
type.
At a broad level I imagine it would look somewhat like this.
Indicator
function runs computations on raw market data at each time tSignal
function fires based on results of Indicator
calculationsRule
dictates what action to take when the Signal
is triggeredRule
is processed, it should should output an Order
Order
object should then be placed in an order queue to be handled at time t+1Order
"processing" logic should probably depend on a Portfolio
object, which should receive a series of Order
s and make the appropriate adjustments at time t+1 to the position holdings and update the per-asset portfolio weightsQuestions:
Order
to buy an equity constitutes a cash outflow at time t but that the same does not go for a futures contract. But futures contracts should probably have their own logic as well (e.g. initial margin, maintenance margin, etc).When installing the package, you're met with the following message:
ERROR: Unsatisfiable requirements detected for package Strategems [054b7d4e]:
Strategems [054b7d4e] log:
├─possible versions are: 0.0.1-0.0.5 or uninstalled
├─restricted to versions * by an explicit requirement, leaving only versions 0.0.1-0.0.5
└─restricted by julia compatibility requirements to versions: uninstalled — no versions left
The whole Git seems to have been deprecated, is the developer still active?
I'm getting the following error after running the example from the README with a clean install of Julia 1.8. I've installed the package using the github URL directly since I've seen some suggestions to do that rather than just adding the package using pkg> add Strategems. Any assistance would be greatly appreciated! Looks like a fantastic package.
Executing task: C:\Program Files\Julia-1.8.3\bin\julia.exe --color=yes --project=C:\Users\mike_.julia\environments\v1.8 c:\data\src\juliaTrader\main.jl
WARNING: both IOExtras and Base export "closewrite"; uses of it in module StreamRequest must be qualified
WARNING: both IOExtras and Base export "closewrite"; uses of it in module ConnectionPool must be qualified
ERROR: LoadError: UndefVarError: closewrite not defined
Stacktrace:
[1] request(::Type{HTTP.StreamRequest.StreamLayer{Union{}}}, io::HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}, req::HTTP.Messages.Request, body::Vector{UInt8}; reached_redirect_limit::Bool, response_stream::Nothing, iofunction::Nothing, verbose::Int64, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HTTP.StreamRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\StreamRequest.jl:83
[2] request(::Type{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}, url::HTTP.URIs.URI, req::HTTP.Messages.Request, body::Vector{UInt8}; proxy::Nothing, socket_type::Type, reuse_limit::Int64, kw::Base.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
@ HTTP.ConnectionRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\ConnectionRequest.jl:96
[3] request(::Type{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}, ::HTTP.URIs.URI, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
@ HTTP.ExceptionRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\ExceptionRequest.jl:19
[4] (::Base.var"#88#90"{Base.var"#88#89#91"{ExponentialBackOff, HTTP.RetryRequest.var"#2#3"{Bool, HTTP.Messages.Request}, typeof(HTTP.request)}})(::Type, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
@ Base .\error.jl:296
[5] #request#1
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\RetryRequest.jl:44 [inlined]
[6] request(::Type{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}; http_version::VersionNumber, target::String, parent::Nothing, iofunction::Nothing, kw::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:reached_redirect_limit,), Tuple{Bool}}})
@ HTTP.MessageRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\MessageRequest.jl:51
[7] request(::Type{HTTP.BasicAuthRequest.BasicAuthLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}; kw::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:reached_redirect_limit,), Tuple{Bool}}})
@ HTTP.BasicAuthRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\BasicAuthRequest.jl:28
[8] request(::Type{HTTP.RedirectRequest.RedirectLayer{HTTP.BasicAuthRequest.BasicAuthLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}; redirect_limit::Int64, forwardheaders::Bool, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HTTP.RedirectRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\RedirectRequest.jl:24
[9] request(::Type{HTTP.RedirectRequest.RedirectLayer{HTTP.BasicAuthRequest.BasicAuthLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8})
@ HTTP.RedirectRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\RedirectRequest.jl:18
[10] request(method::String, url::String, h::Vector{Pair{SubString{String}, SubString{String}}}, b::Vector{UInt8}; headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}, query::Nothing, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HTTP C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:314
[11] request (repeats 2 times)
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:312 [inlined]
[12] #get#12
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:391 [inlined]
[13] get
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:391 [inlined]
[14] quandl(code::String; from::String, thru::String, freq::Char, calc::String, sort::Char, rows::Int64, auth::String)
@ Temporal C:\Users\mike_.julia\packages\Temporal\aaVHO\src\data\quandl.jl:77
[15] quandl
@ C:\Users\mike_.julia\packages\Temporal\aaVHO\src\data\quandl.jl:50 [inlined]
[16] datasource(asset::String; save_downloads::Bool)
@ Main c:\data\src\juliaTrader\main.jl:11
[17] datasource
@ c:\data\src\juliaTrader\main.jl:6 [inlined]
[18] gather!(universe::Universe; source::typeof(datasource), verbose::Bool)
@ Strategems C:\Users\mike_.julia\packages\Strategems\9FJXr\src\model\universe.jl:41
[19] top-level scope
@ c:\data\src\juliaTrader\main.jl:22
in expression starting at c:\data\src\juliaTrader\main.jl:22
caused by: EOFError: read end of file
Stacktrace:
[1] read_to_buffer(t::HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}, sizehint::Int64)
@ HTTP.ConnectionPool C:\Users\mike_.julia\packages\HTTP\IAI92\src\ConnectionPool.jl:252
[2] readuntil(t::HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}, f::Function, sizehint::Int64)
@ HTTP.ConnectionPool C:\Users\mike_.julia\packages\HTTP\IAI92\src\ConnectionPool.jl:271
[3] readuntil
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\ConnectionPool.jl:269 [inlined]
[4] readheaders
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\Messages.jl:471 [inlined]
[5] startread(http::HTTP.Streams.Stream{HTTP.Messages.Response, HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}})
@ HTTP.Streams C:\Users\mike_.julia\packages\HTTP\IAI92\src\Streams.jl:155
[6] macro expansion
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\StreamRequest.jl:67 [inlined]
[7] macro expansion
@ .\task.jl:454 [inlined]
[8] request(::Type{HTTP.StreamRequest.StreamLayer{Union{}}}, io::HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}, req::HTTP.Messages.Request, body::Vector{UInt8}; reached_redirect_limit::Bool, response_stream::Nothing, iofunction::Nothing, verbose::Int64, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HTTP.StreamRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\StreamRequest.jl:57
[9] request(::Type{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}, url::HTTP.URIs.URI, req::HTTP.Messages.Request, body::Vector{UInt8}; proxy::Nothing, socket_type::Type, reuse_limit::Int64, kw::Base.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
@ HTTP.ConnectionRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\ConnectionRequest.jl:96
[10] request(::Type{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}, ::HTTP.URIs.URI, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
@ HTTP.ExceptionRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\ExceptionRequest.jl:19
[11] (::Base.var"#88#90"{Base.var"#88#89#91"{ExponentialBackOff, HTTP.RetryRequest.var"#2#3"{Bool, HTTP.Messages.Request}, typeof(HTTP.request)}})(::Type, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
@ Base .\error.jl:296
[12] #request#1
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\RetryRequest.jl:44 [inlined]
[13] request(::Type{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}; http_version::VersionNumber, target::String, parent::Nothing, iofunction::Nothing, kw::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:reached_redirect_limit,), Tuple{Bool}}})
@ HTTP.MessageRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\MessageRequest.jl:51
[14] request(::Type{HTTP.BasicAuthRequest.BasicAuthLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}; kw::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:reached_redirect_limit,), Tuple{Bool}}})
@ HTTP.BasicAuthRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\BasicAuthRequest.jl:28
[15] request(::Type{HTTP.RedirectRequest.RedirectLayer{HTTP.BasicAuthRequest.BasicAuthLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}; redirect_limit::Int64, forwardheaders::Bool, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HTTP.RedirectRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\RedirectRequest.jl:24
[16] request(::Type{HTTP.RedirectRequest.RedirectLayer{HTTP.BasicAuthRequest.BasicAuthLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer{Union{}}}}}}}}}, method::String, url::HTTP.URIs.URI, headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8})
@ HTTP.RedirectRequest C:\Users\mike_.julia\packages\HTTP\IAI92\src\RedirectRequest.jl:18
[17] request(method::String, url::String, h::Vector{Pair{SubString{String}, SubString{String}}}, b::Vector{UInt8}; headers::Vector{Pair{SubString{String}, SubString{String}}}, body::Vector{UInt8}, query::Nothing, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HTTP C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:314
[18] request (repeats 2 times)
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:312 [inlined]
[19] #get#12
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:391 [inlined]
[20] get
@ C:\Users\mike_.julia\packages\HTTP\IAI92\src\HTTP.jl:391 [inlined]
[21] quandl(code::String; from::String, thru::String, freq::Char, calc::String, sort::Char, rows::Int64, auth::String)
@ Temporal C:\Users\mike_.julia\packages\Temporal\aaVHO\src\data\quandl.jl:77
[22] quandl
@ C:\Users\mike_.julia\packages\Temporal\aaVHO\src\data\quandl.jl:50 [inlined]
[23] datasource(asset::String; save_downloads::Bool)
@ Main c:\data\src\juliaTrader\main.jl:11
[24] datasource
@ c:\data\src\juliaTrader\main.jl:6 [inlined]
[25] gather!(universe::Universe; source::typeof(datasource), verbose::Bool)
@ Strategems C:\Users\mike_.julia\packages\Strategems\9FJXr\src\model\universe.jl:41
[26] top-level scope
@ c:\data\src\juliaTrader\main.jl:22
Should be able to run multiple backtests in parallel when doing parameter optimization runs.
When defining a ParameterSet
object with ranges corresponding to each of its variables (i.e. the arg_ranges
member), currently there isn't any way to constrain the parameter space using the relationships between the variables.
There should be logic to support these kinds of inter-variable relationship constraints. For example, take a simple strategy using two moving averages, one with a short lookback period and one with a long lookback period. Suppose our rule is to go long when the short MA crosses over the long MA, and we want to simulate this strategy over a bunch of pairs of lookback windows. There should be logic to constrain the simulation such that the short MA's lookback must be less than the long MA's lookback.
Add the ability to define a signal or rule with logical operators. For example:
siglong = @signal MAMA ↑ FAMA || MAMA == FAMA
I've installed and then reinstalled Julia 0.7.0v from the official site, made a clean git from the latest pull from the author, then, proceeded to run the examples/mama.jl and the test/runtest.jl, both didn't sucessfully compile and gave me the following stack:
**ERROR: LoadError: LoadError: syntax: "..." expression outside call**
Stacktrace:
[1] include at .\boot.jl:317 [inlined]
[2] include_relative(::Module, ::String) at .\loading.jl:1038
[3] include at .\sysimg.jl:29 [inlined]
[4] include(::String) at C:\Users\MyUser\.julia\packages\Strategems\PJiUR\src\Strategems.jl:3
[5] top-level scope at none:0
[6] include at .\boot.jl:317 [inlined]
[7] include_relative(::Module, ::String) at .\loading.jl:1038
[8] include(::Module, ::String) at .\sysimg.jl:29
[9] top-level scope at none:2
[10] eval at .\boot.jl:319 [inlined]
[11] eval(::Expr) at .\client.jl:399
[12] top-level scope at .\none:3
in expression starting at C:\Users\MyUser\.julia\packages\Strategems\PJiUR\src\rule.jl:15
in expression starting at C:\Users\MyUser\.julia\packages\Strategems\PJiUR\src\Strategems.jl:34
ERROR: LoadError: Failed to precompile Strategems [054b7d4e-9922-5ad3-8b46-7dbe695a681f] to C:\Users\laughing man\.julia\compiled\v0.7\Strategems\qq9u1.ji.
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] macro expansion at .\logging.jl:313 [inlined]
[3] compilecache(::Base.PkgId, ::String) at .\loading.jl:1185
[4] _require(::Base.PkgId) at .\logging.jl:311
[5] require(::Base.PkgId) at .\loading.jl:852
[6] macro expansion at .\logging.jl:311 [inlined]
[7] require(::Module, ::Symbol) at .\loading.jl:834
[8] include at .\boot.jl:317 [inlined]
[9] include_relative(::Module, ::String) at .\loading.jl:1038
[10] include(::Module, ::String) at .\sysimg.jl:29
[11] exec_options(::Base.JLOptions) at .\client.jl:239
[12] _start() at .\client.jl:432
in expression starting at C:\User\MyUser\Documents\Strategems.jl\examples\mama.jl:1
Which leads us again to:
macro rule(logic::Expr, args...)
trigger = :($(logic.args[2]))
#action = :($(logic.args[3])$((args...)))
action = :($(logic.args[3]))
args = :($(args))
return esc(:(Rule($trigger, $action, $args)))
end
I have a vague idea on how to fix the code, but since it's a default error, I thought I'd report as an issue.
Need to write more thorough documentation for package functionality.
Strategems.jl/test/runtests.jl
Line 8 in 133b58f
You should use instead nested testsets to isolate tests and "share" variables
Hi there,
So I'm using the IDE from Julia Pro 0.6.1.1.
I've created a new directory called JuliaTrading.jl
. I've placed the mama.jl
file inside of it, but called it strat.jl
.
I use the IDE's console to run Pkg.add("Strategems")
which works successfully.
Then I use the IDE's "Julia -> Run File" feature, which returns:
LoadError: UndefVarError: @signal not defined
while loading /Users/balupton/Projects/trading/JuliaTrading.jl/strat.jl, in expression starting on line 30
include_string(::String, ::String) at loading.jl:522
include_string(::Module, ::String, ::String) at Compat.jl:464
(::Atom.##57#60{String,String})() at eval.jl:74
withpath(::Atom.##57#60{String,String}, ::String) at utils.jl:30
withpath(::Function, ::String) at eval.jl:38
macro expansion at eval.jl:72 [inlined]
(::Atom.##56#59{Dict{String,Any}})() at task.jl:80
It also happens when installing the package via Pkg.clone("https://github.com/dysonance/Strategems.jl")
strat.jl
is:
using Strategems, Temporal, Indicators, Base.Dates
using Base.Test
# define universe and gather data
assets = ["CHRIS/CME_CL1", "CHRIS/CME_RB1"]
universe = Universe(assets)
function datasource(asset::String; save_downloads::Bool=true)::TS
savedata_path = Pkg.dir("Strategems", "data/$asset.csv")
if isfile(savedata_path)
return Temporal.tsread(savedata_path)
else
X = quandl(asset)
if save_downloads
Temporal.tswrite(X, savedata_path)
end
return X
end
end
gather!(universe, source=datasource)
# define indicators and parameter space
arg_names = [:fastlimit, :slowlimit]
arg_defaults = [0.5, 0.05]
arg_ranges = [0.01:0.01:0.99, 0.01:0.01:0.99]
paramset = ParameterSet(arg_names, arg_defaults, arg_ranges)
f(x; args...) = Indicators.mama(x; args...)
indicator = Indicator(f, paramset)
# define signals that will trigger trading decisions
siglong = @signal MAMA ↑ FAMA
sigshort = @signal MAMA ↓ FAMA
sigexit = @signal MAMA .== FAMA
# define the trading rules
longrule = @rule siglong → long 100
shortrule = @rule sigshort → short 100
exitrule = @rule sigexit → liquidate 1.0
rules = (longrule, shortrule, exitrule)
# run strategy
strat = Strategy(universe, indicator, rules)
backtest!(strat)
optimize!(strat, samples=10)
Instead of running all possible combinations of all parameters in the space, it probably wouldn't be too bad to implement functionality that randomly samples a user-suppled number n parameter combinations from the entire space. Then you could run an optimization much more quickly if desired while still getting a broader span of the parameter space than doing the combinations sequentially.
Should also support an argument that allows setting the seed of the random number generator.
Bonus advantage: could greatly expedite test cases.
Hello,
Just a comment about tests not really an issue... you should probably use @testset
Kind regards
julia> using Strategems
julia> arg_names = [:fastlimit, :slowlimit]
2-element Array{Symbol,1}:
:fastlimit
:slowlimit
julia> arg_defaults = [0.5, 0.05]
2-element Array{Float64,1}:
0.5
0.05
julia> arg_ranges = [0.01:0.01:0.99, 0.01:0.01:0.99]
2-element Array{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},1}:
0.01:0.01:0.99
0.01:0.01:0.99
julia> paramset = ParameterSet(arg_names, arg_defaults, arg_ranges)
Parameters:
(1) fastlimit → 0.5 ∈ {0.01:0.01:0.99} :: Float64
(2) slowlimit → 0.05 ∈ {0.01:0.01:0.99} :: Float64
julia> get_run_params(paramset)
ERROR: function get_param_combos does not accept keyword arguments
Stacktrace:
[1] kwfunc(::Any) at ./boot.jl:237
[2] #get_run_params#4(::Int64, ::Function, ::Strategems.ParameterSet) at /home/femto/.julia/v0.6/Strategems/src/paramset.jl:50
[3] get_run_params(::Strategems.ParameterSet) at /home/femto/.julia/v0.6/Strategems/src/paramset.jl:49
Hello,
Python have an interesting library with a nice API.
https://pypet.readthedocs.io/
Maybe you should consider something like this.
This Julia parameter exploration toolkit could be even be a standalone project (with few dependencies).
Similar discussion https://www.quantopian.com/posts/parameter-exploration-slash-running-several-backtests-from-notebook
These discussions about generators and Julia might be interesting for that purpose https://discourse.julialang.org/t/pygen-python-style-generators/3451
https://discourse.julialang.org/t/ann-resumablefunctions/5711
Kind regards
I found very interesting this tool, so I started from the example posted in the README but I was not able to make it work. I'm using Julia 1.4.2. Here is the full stack trace, but the error occurs when creating the Universe instance (apparently, some bad access in an empty list):
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.4.2 (2020-05-23)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> using Strategems, Indicators, Temporal, Dates
julia> assets = ["CHRIS/CME_CL1", "CHRIS/CME_RB1"]
2-element Array{String,1}:
"CHRIS/CME_CL1"
"CHRIS/CME_RB1"
julia> universe = Universe(assets)
# Universe:
Asset 1: CHRIS/CME_CL1
Error showing value of type Universe:
ERROR: BoundsError: attempt to access 0-element Array{Date,1} at index [1]
Stacktrace:
[1] getindex(::Array{Date,1}, ::Int64) at ./array.jl:788
[2] show(::IOContext{REPL.Terminals.TTYTerminal}, ::Universe) at /home/leferrad/.julia/packages/Strategems/TJzbq/src/universe.jl:63
[3] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::Universe) at ./multimedia.jl:47
[4] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:137
[5] display(::REPL.REPLDisplay, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:141
[6] display(::Any) at ./multimedia.jl:323
[7] #invokelatest#1 at ./essentials.jl:712 [inlined]
[8] invokelatest at ./essentials.jl:711 [inlined]
[9] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:161
[10] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:146
[11] (::REPL.var"#do_respond#38"{Bool,REPL.var"#48#57"{REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:729
[12] #invokelatest#1 at ./essentials.jl:712 [inlined]
[13] invokelatest at ./essentials.jl:711 [inlined]
[14] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/LineEdit.jl:2354
[15] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:1055
[16] run_repl(::REPL.AbstractREPL, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:206
[17] (::Base.var"#764#766"{Bool,Bool,Bool,Bool})(::Module) at ./client.jl:383
[18] #invokelatest#1 at ./essentials.jl:712 [inlined]
[19] invokelatest at ./essentials.jl:711 [inlined]
[20] run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) at ./client.jl:367
[21] exec_options(::Base.JLOptions) at ./client.jl:305
[22] _start() at ./client.jl:484
Let me know if you need something else to reproduce this error, in order to detect the bug and make a PR to fix it.
It should have helped to catch #21
Hello,
We should have a sample data project
(it could be in a separate repository)
I think it will be better to have sample data close to something that can be use in backtesting production.
I think we should split data directory from datasource and into bars
, ticks
, orderbooks
I also think that we should use "round" date range for data (chunk of data)
A possible organization could be
data
datasource1
bars
D
2010
GOOG.csv
another_ticker (to define).csv
2011
GOOG.csv
another_ticker (to define).csv
2012
GOOG.csv
another_ticker (to define).csv
2013
GOOG.csv
another_ticker (to define).csv
2014
GOOG.csv
another_ticker (to define).csv
2015
GOOG.csv
another_ticker (to define).csv
ticks
2015
2015-02
2015-02-01
MSFT.csv
AMZN.csv
GOOG.csv
This kind of organization will urge us to work with chunk of data (especially if we want to deal with tick data)
Kind regards
PS : You might have a look at
mhallsmoore/qstrader#106
Can you add live trading connectors also.
Hello,
ParameterSet
currently doesn't support constraints among parameters.
Here is a short implementation
import Base: show
const TABWIDTH = 4
const TAB = ' ' ^ TABWIDTH
mutable struct ParameterSet
arg_names::Vector{Symbol}
arg_defaults::Vector
arg_ranges::Vector
arg_types::Vector{<:Type}
n_args::Int
constraints::Vector
#TODO: refactor out the arg_ prefix (its redundant if they all start with it)
function ParameterSet(arg_names::Vector{Symbol},
arg_defaults::Vector,
arg_ranges::Vector=[x:x for x in arg_defaults];
constraints::Vector = [p -> true])
@assert length(arg_names) == length(arg_defaults) == length(arg_ranges)
@assert eltype.(arg_defaults) == eltype.(arg_ranges)
arg_types::Vector{<:Type} = eltype.(arg_defaults)
return new(arg_names, arg_defaults, arg_ranges, arg_types, length(arg_names), constraints)
end
end
function generate_nt_combinations(ps::ParameterSet)
itr = Iterators.product(ps.arg_ranges...)
itr = Iterators.map(t -> (; zip(ps.arg_names, t)...), itr)
for constraint in ps.constraints
itr = Iterators.filter(constraint, itr)
end
collect(itr)
end
Usage:
arg_names = [:fastlimit, :slowlimit, :x]
arg_defaults = [0.5, 0.05, 0.01]
arg_ranges = [0.01:0.01:1.00, 0.01:0.01:1.00, 0.01:0.01:1.00]
constraints = [p -> p.fastlimit < p.slowlimit]
paramset = ParameterSet(arg_names, arg_defaults, arg_ranges, constraints=constraints)
params = generate_nt_combinations(paramset)
params
returns
495000-element Vector{NamedTuple{(:fastlimit, :slowlimit, :x), Tuple{Float64, Float64, Float64}}}:
(fastlimit = 0.01, slowlimit = 0.02, x = 0.01)
(fastlimit = 0.01, slowlimit = 0.03, x = 0.01)
(fastlimit = 0.02, slowlimit = 0.03, x = 0.01)
(fastlimit = 0.01, slowlimit = 0.04, x = 0.01)
(fastlimit = 0.02, slowlimit = 0.04, x = 0.01)
...
(fastlimit = 0.96, slowlimit = 1.0, x = 1.0)
(fastlimit = 0.97, slowlimit = 1.0, x = 1.0)
(fastlimit = 0.98, slowlimit = 1.0, x = 1.0)
(fastlimit = 0.99, slowlimit = 1.0, x = 1.0)
which can easily be transformed as DataFrame
:
using DataFrame
DataFrame(params)
which returns
495000×3 DataFrame
Row │ fastlimit slowlimit x
│ Float64 Float64 Float64
────────┼───────────────────────────────
1 │ 0.01 0.02 0.01
2 │ 0.01 0.03 0.01
3 │ 0.02 0.03 0.01
4 │ 0.01 0.04 0.01
5 │ 0.02 0.04 0.01
6 │ 0.03 0.04 0.01
7 │ 0.01 0.05 0.01
8 │ 0.02 0.05 0.01
9 │ 0.03 0.05 0.01
10 │ 0.04 0.05 0.01
11 │ 0.01 0.06 0.01
⋮ │ ⋮ ⋮ ⋮
494991 │ 0.9 1.0 1.0
494992 │ 0.91 1.0 1.0
494993 │ 0.92 1.0 1.0
494994 │ 0.93 1.0 1.0
494995 │ 0.94 1.0 1.0
494996 │ 0.95 1.0 1.0
494997 │ 0.96 1.0 1.0
494998 │ 0.97 1.0 1.0
494999 │ 0.98 1.0 1.0
495000 │ 0.99 1.0 1.0
494979 rows omitted
Maybe it can help.
Kind regards
PS: see also #8
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.