Need help with db put/get

Section for discussions related to indicators, use of indicators, and building of trading stategies using indicators.

Moderator: admin

Need help with db put/get

Postby Silverthorn » Wed Nov 13, 2019 1:41 am

I have an indicator that I wrote some years ago and am now trying to finish.

I am having trouble saving and retreating values to a db.

My code I am struggling with is

function Init()
indicator:type(core.Indicator);
indicator:name("BAHA");
indicator:description("BAHA");
indicator:setTag("group", "BAHA");
indicator:setTag("replaceSource","t");
indicator:requiredSource(core.Bar);
indicator.parameters:addString ("dbManager", "Database", "", "UseSaved");
indicator.parameters:addStringAlternative ("dbManager", "UseSaved", "", "UseSaved");
indicator.parameters:addStringAlternative ("dbManager", "UseLocal", "", "UseLocal");
indicator.parameters:addStringAlternative ("dbManager", "Save", "", "Save");
end

function Prepare()
instance:ownerDrawn(true);
source = instance.source;

local dbname = "BAHADB" .. source:name() .. instance.source:barSize ();
require("storagedb")
db = storagedb.get_db(dbname);
local dbManager = instance.parameters.dbManager;
if dbManager == "Save" then
db:put(tostring("SR_Offset"),tostring(SR_Offset));
db:put(tostring("SR_Confirmation"),tostring(SR_Confirmation));
db:put(tostring("Speed"),tostring(Speed));
end
if dbManager == "UseSaved" then
SR_Offset = tonumber(db:get (tostring("SR_Offset"), 0));
SR_Confirmation = tonumber(db:get (tostring("SR_Confirmation"), 0));
Speed = tonumber(db:get (tostring("Speed"), 0));
else
SR_Confirmation = instance.parameters.SR_Confirmation;
SR_Offset = instance.parameters.SR_Offset;
Speed = instance.parameters.Speed;
end

When I run UseLocal no problem.
When I save everything is fine.
When I try to UseSaved I get an error saying that I am attempting to perform arithmetic on upvalue "SR_Confirmation" (a nil value)

I'm not really understanding what makes it an upvalue but I think my problem is that I am using strings and numbers incorrectly.
Can anybody give me some help?
User avatar
Silverthorn
 
Posts: 69
Joined: Fri Nov 08, 2013 12:29 am
Location: Brisbane Australia

Re: Need help with db put/get

Postby Silverthorn » Wed Nov 13, 2019 3:15 am

Well I found the problem myself.

I was trying to load the db with values that I only populated afterwards.

SR_Confirmation = instance.parameters.SR_Confirmation;
SR_Offset = instance.parameters.SR_Offset;
Speed = instance.parameters.Speed;

needs to be before

db:put(tostring("SR_Offset"),tostring(SR_Offset));
db:put(tostring("SR_Confirmation"),tostring(SR_Confirmation));
db:put(tostring("Speed"),tostring(Speed));
User avatar
Silverthorn
 
Posts: 69
Joined: Fri Nov 08, 2013 12:29 am
Location: Brisbane Australia

Re: Need help with db put/get

Postby Loggy48 » Sat Jan 02, 2021 7:40 am

You don't need the tostring() for the first parameter anyway as it is already a character string.

TS uses SQLite so you can see what is in the database by using the DB Broswer for SQLite (once the program has finished of course). The Indicore debugger will show you the structure of the sytem offer etc tables. The database is stored in persistent/luastorage.db, not in a file specified.

All the binding does is to store data as strings so if you want to store a whole Lua table, this must be written into a lua-readable string to start with. Therefore numbers are still stored as text and functions in tables cannot be stored (they appear to be stored but cannot be reused). Functions in text can of course be stored.

Don't forget that SQLite cannot by default store binary data - you have to encode the number as a blob but I doubt it is ever worth it. A useful feature is the open_memory() command which will store data in memory but that of course is lost when the program closes and if you use Linux you can store files in memory anyway using tmpfs etc in /run/user/<userid> which stays until you remove it or reboot the computer. TS runs in a Windoze environment... :(

You can write out a simple lua file and read it in using dofile but then remember that such a chunk has its own scope so you need to return the data either functions or values into local functions or values [ie local v1,v2,v3 = dofile("myfile") where myfile that specifies v1 etc as functions, variables or tables ends with return v1,v2,v3]

For more extensive database storage it may be better to use SQLite3 as in http://lua.sqlite.org. Here is a simple example modified from the examples directory (using UPDATE or repeated runs will insert additional rows):
Code: Select all
local sqlite3 = require("lsqlite3complete")
local db = sqlite3.open("/my/file/testall.db")
db:exec[[
  UPDATE TABLE test (id INTEGER PRIMARY KEY, content);
  INSERT INTO test VALUES (NULL, 'Hello World');
  INSERT INTO test VALUES (NULL, 'Hello Lua');
  INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
]]
for row in db:nrows("SELECT * FROM test") do
  print(row.id, row.content)
end
db:exec[[
  UPDATE TABLE test1 (col1, col2);
  INSERT INTO test1 VALUES (1, 2);
  INSERT INTO test1 VALUES (2, 4);
  INSERT INTO test1 VALUES (3, 6);
  INSERT INTO test1 VALUES (4, 8);
  INSERT INTO test1 VALUES (5, 10)
]]
do
  local square_error_sum = 0
  local function step(ctx, a, b)
    square_error_sum   = square_error_sum + (a - b)^2
  end
  local function final(ctx)
    ctx:result_number( square_error_sum / ctx:aggregate_count() )
  end
  db:create_aggregate("my_stats", 2, step, final)
end

for my_stats in db:urows("SELECT my_stats(col1, col2) FROM test1")
do print("my_stats:", my_stats) end

for a,b in db:urows("SELECT col1, col2 FROM test1")
do print("a b: ", a, b) end
Loggy48
 
Posts: 81
Joined: Tue Jun 24, 2014 8:39 am
Location: Manchester, UK


Return to Discussions

Who is online

Users browsing this forum: No registered users and 1 guest