Freezing problems with GENIE/Stipple whilst updating using ZMQ feed

Hi there

UPDATE. Decided to run the live system from CLI and caught the freeze event. Got the inspect snapshot, hit browser refresh which woke it up took another inspect snapshot, waited a few seconds to see it running and took a running properly inspect snapshot. Hope this is useful.

all snapshots in next message as they didn’t seem to want to upload into this message

can’t do it today BUT we’ll install the code you wrote into the cron process for 5/8/23.Please note I modified your code slightly as the n variable was outside the while loop. I made it global ( I know I know bad bad ) I didn’t want to mess up your code.

Thanks for the instructions about the inspect, we keep ourselves ignorant about all things web browserish, ironic really as our boss funded sun microsystems and formed the first java fund :wink:

In answer to your question. YEP the event timing can alter dramatically. For this functionality we can introduce a delay in the ZMQ if we have to. you might have already introduced a delay with the print statement in your loop. We’ll have to see what happens when we remove it but for now we’ll leave it in.

It’s not a problem as 1 sec for this data isn’t a problem. I think it would be useful to track this down for YOUR purposes so we’ll just let the data flow at the normal rate. We know that the data is flowing correctly, that the dataframe ( in our code and yours) updates effectively. The only thing not working consistently is the model.

have an excellent one

ps here is the code we will be using on 5/8/23 for the run. Please note the global bodge for n in the loop. We know it’s a no no but we didn’t want to mess your code up. Let us know if you have a newer version you want us to try.

using Stipple
using StippleUI
using StipplePlotly
using CSV, DataFrames, Dates , Logging
using ZMQ

log_date = Dates.format(now(),"yyyy_mm_dd_HH_MM")
log_name = "/home/dave/tontine_2022/data/logs/tontine2_log_" * log_date * ".log"
io = open( log_name, "w+")
logger = SimpleLogger(io)
global_logger(logger)


dash_columns = ["sym","close","price","sdmove","hv20","hv10","hv5","iv","iv%ile","prc%ile","ern_days"]

df = DataFrame([col => (col == "sym" ? String : Float64)[] for col in dash_columns])
df_table = Observable(df)

zmq_dash = Dict("LAST" => "price","CLOSE" => "close","OPTION_IMPLIED_VOL" => "iv","OPTION_HISTORICAL_VOL" => "iv",
                         "VOLUME"  => "volume","IV" => "iv","IV_PERCENTILE" => "iv%ile" ,"HV20" => "hv20",
                         "HV10" => "hv10","HV5" => "hv5" ,"PRICE_PERCENTILE" => "prc%ile","EARNDAYS" => "ern_days")


@vars TontineModel begin
    tontine_data::R{DataTable} = DataTable(df_table[])
    tontine_data_pagination::DataTablePagination = DataTablePagination(rows_per_page=100) #9/11/22
end

function ui(model::TontineModel)
    page(
        model, class="container", title="title TONTINE2 ", head_content=Genie.Assets.favicon_support(),

        [
        heading( "heading Tontine2 5555 9/11/22 from 9_11_22_stpl_pull.jl pag = 100 px = 3000"  )

        row([
            cell(class="st-module", [
            h5("h5 tontine data")
            table(:tontine_data;
            style="height: 3000px;",
            pagination=:tontine_data_pagination) # 9/11/22 added pagination
            ])
        ])
        ]
    )
end

function handlers(model)
    on(model.isready) do isready
        isready || return
        model.tontine_data[] = DataTable(df_table[])
    end

    on(df_table) do new_table
        model.isready[] || return
        model.tontine_data[] = DataTable(new_table)
    end

    model
end

route("/") do #9/12/22 https://discourse.julialang.org/t/noob-needs-help-debugging-and-understanding-reactive-models/87038/12
    global model
    model = init(TontineModel)
    model |> handlers |> ui |> html #  = has lowest precedence
end

up()       # up(9000; async = true, server = Stipple.bootstrap())


# it is good practice to append a '!' to the function name if that function changes the content of one or more variables
function price_calcs!(df, sym_in)

    #println( "entering price_calcs " ) 
    row = df[findfirst(==(sym_in), df.sym), :]
    expected_move = round(row.iv / 19.896 , digits = 2)
    change = round((row.price - row.close) / row.close * 100  , digits = 2)
    sdmove = round(change / expected_move, digits = 2)

    isinf(sdmove) && (sdmove = 999.99)
    
    try 
        # row is only a view on the DataFrame, so this updates the DataFrame!
        row.sdmove = sdmove
    catch y
        # println("ADDING SDMOVE CATCH something went wrong with sdmove into df_table : ", y)
        @info "adding SDMOVE something went wrong error : " y 
        row.sd_move = 999.00
    end

end

function receive!(socket, df_table)  
    message = String(ZMQ.recv(socket))
    @info "message : $(now()) : " message    # 9/11/22 https://julialogging.github.io/tutorials/logging-basics/
    flush(io)

    println("Received request: $message")

    if message == "END"
        println("dying")
        println(df_table)
        @info "=================================================================================================================> $(now())  got end dying"
        @info df_table

        try 
            ZMQ.close(socket)
            ZMQ.close(context)
            return 1
        catch zmq_error
            @info "*********************************************************==> something went wrong with closing zmq sockets => " zmq_error ZMQ.zmq_errno()
        end

    end

    in_source, sym_in, field_in, value_in = split( message , "~")
    value_fl = parse(Float64, value_in) # convert to Float64
    
    field_out = zmq_dash[field_in] # ie field_in "OPTION_IMPLIED_VOL" => field_out "iv"
    try
        #println("message to add : ", in_source," ",sym_in," ",field_out," " ,value_in)
        sym_in in df_table[].sym || push!(df_table[], (sym_in, 0.0, 0.0, 0.0, 0.0 , 0.0, 0.0 , 0.0 , 0.0 , 0.0 , 0.0))

        df_table[][findfirst(==(sym_in), df_table[].sym), Symbol(field_out)] = value_fl

        if field_out == "price" 
            price_calcs!(df_table[], sym_in)
        end

        try 
            notify(df_table)
        catch f
            #println(" NOTIFY CATCH  something went wrong with df_table : ", f)
            #println("sym_in :", sym_in," field_out : ", field_out)
            @info " $(now())    NOTIFY CATCH  something went wrong with df_table :" f
        end
    catch e
        @error "** PROBLEM WITH DF UPDATE >  "  field_out  e 
    end
    return 0
end

# ---------- Main ---------

empty!(df_table[])
notify(df_table)
context = Context()
socket = Socket(context, PULL)
ZMQ.bind(socket, "tcp://*:5555")

@info " $(now())  ===>>>    starting IN Socket 5555" 
flush(io)

n = 1
while true
    print(lpad("$n", 5, '0'), "> ")
    receive!(socket, df_table) == 0 || break
    global n += 1
end
```