femtotrader / TALib.jl

A Julia wrapper for TA-Lib
Other
50 stars 11 forks source link

Metaprogramming / use macros #5

Open femtotrader opened 8 years ago

femtotrader commented 8 years ago

We might use macros instead of code generation using strings.

see http://docs.julialang.org/en/release-0.5/manual/metaprogramming/

http://stackoverflow.com/questions/37230071/metaprogramming-julia-functions-with-args-and-keyword-args/37230249#37230249

femtotrader commented 8 years ago

(You) should return an expression from macros. To make code an expression, decorate your code with either :(....) or quote ... end. Also, $ is valid only for expressions and strings. Lastly, there is a hygiene issue with macros. In order to keep $funcname intact you need esc around it. Here is corrected code

julia> macro GEN_FUNC(funcname)  
           fname=esc(funcname)  
           quote  
               function $fname(a, b, x=1, y=2)  
                   return x  
               end  
           end  
       end  

julia> macroexpand(:(@GEN_FUNC testing))  
quote  # none, line 4:  
    function testing(#21#a,#22#b,#23#x=1,#24#y=2) # none, line 5:  
        return #23#x  
    end  
end

Update: Here is how myfunc can be manually constructed (Hint:I made it an expression with quote ... end and cheated from that)

julia> f_body=:(x+y)
:(x + y)

julia> f_parameters=Expr(:parameters, Expr(:kw,:x,Int64(1)), Expr(:kw,:y,Float64(2)))
:($(Expr(:parameters, :(x=1), :(y=2.0))))

julia> f_call=Expr(:call,:myfunc,f_parameters,:(a::Array{Float64,1}),:(b::Array{Float64,1}))
:(myfunc(a::Array{Float64,1},b::Array{Float64,1}; x=1,y=2.0))

julia> f_declare=Expr(:function,f_call,f_body)
:(function myfunc(a::Array{Float64,1},b::Array{Float64,1}; x=1,y=2.0)
        x + y
    end)

julia> eval(f_declare)
myfunc (generic function with 1 method)

julia> myfunc(2,3)
ERROR: MethodError: `myfunc` has no method matching myfunc(::Int64, ::Int64)

julia> myfunc([2.],[3.])
3.0

julia> myfunc([2.],[3.];x=4,y=8.)
12.0
femtotrader commented 7 years ago

Example of @eval usage

https://github.com/JuliaComputing/ArrayFire.jl/blob/009838ffa6071d904d8622b1988ac69bf85ac349/src/signal.jl#L35

https://github.com/stevengj/DecFP.jl/blob/master/src/DecFP.jl

WIP

using TALib: get_dict_of_ta_func, d_typ_to_c
include("src/tools.jl")
using DataStructures: OrderedDict

d = get_dict_of_ta_func()
d_code = OrderedDict{Symbol,Expr}()

for (symb_func, func_info) in d
    s_doc_Index = ""
    s_doc_RequiredInputArguments = ""
    s_doc_OptionalInputArguments = ""
    s_doc_OutputArguments = ""

    params = String[]
    ctypes = String[]
    for arg = ["startIdx", "endIdx"]
        varname = uncamel(arg)
        vartyp = "Cint"
        push!(params, varname)
        push!(ctypes, vartyp)
        s_doc_Index *= "\n        - $arg::$vartyp"
    end

    for arg = func_info["RequiredInputArguments"]
        varname = replace_var(arg["Name"])
        vartyp = d_typ_to_c[arg["Type"]]
        push!(params, string(varname))
        push!(ctypes, string(vartyp))
        s_doc_RequiredInputArguments *= "\n        - $varname::$vartyp"
    end

    for arg = func_info["OptionalInputArguments"]
        varname = fix_varname(arg["Name"])
        vartyp = d_typ_to_c[arg["Type"]]
        push!(params, varname)
        push!(ctypes, string(vartyp))
        s_doc_OptionalInputArguments *= "\n        - $varname::$vartyp"
    end

    for arg = ["outBegIdx", "outNbElement"]
        varname = arg #uncamel(arg)
        push!(params, varname)
        push!(ctypes, "Ref{Cint}")
    end

    for arg = func_info["OutputArguments"]
        varname = arg["Name"]
        vartyp = d_typ_to_c[arg["Type"]]
        push!(params, varname)
        push!(ctypes, string(vartyp))
        s_doc_OutputArguments *= "\n        - $varname::$vartyp"
    end

    params = join(params, ", ")
    ctypes = join(ctypes, ", ")

    funcname = "_TA_" * string(symb_func)
    symb_func = Symbol(funcname)
    c_funcname = "TA_" * string(symb_func)
    ret_typ = "TA_RetCode"

    expression = quote
        """
            $($funcname)(start_idx, end_idx, price_open, price_high, price_low, price_close, outBegIdx, outNbElement, outInteger)

        Up/Down-gap side-by-side white lines (CdlGapSideSideWhite)

            Pattern Recognition

            Level: 0 - raw

        Arguments:

            Indexes:
                - startIdx::Cint
                - endIdx::Cint

            RequiredInputArguments:$($s_doc_RequiredInputArguments)

            OptionalInputArguments:$($s_doc_OptionalInputArguments)

            OutputArguments:$($s_doc_OutputArguments)

        Returns:
            ::$($ret_typ)
        """        
        function ($symb_func)()
            "..."
        end
    end
    d_code[symb_func] = expression  # save expression to d_code dictionary (to see generated source code)
    #eval(expression)
end

println(d_code)
println(repeat("=", 10))
println(d_code[:_TA_COS])

or


    @eval function ($funcname)()
        "..."
    end