local Grammar = require 'grammar' local GA = require 'ga' local data = {} local csvFile = io.open('HistoricalData_1735758980544-AAPL.csv') local skip = true for line in csvFile:lines() do if skip then skip = false else local tbl = {} for lineValue in string.gmatch(line, '[^,]+') do table.insert(tbl, lineValue) end table.insert(data, tbl) end end local metaproduction = {} metaproduction[""] = {{''}} metaproduction[""] = { {}, {'', ''} } metaproduction[""] = {{ 'defun(', '', ')\n' }} metaproduction[""] = { {'0'}, {'1+', ''} } local metagrammar = Grammar.createGrammar(metaproduction, {}) local production = {} production[""]={{''}} production[""]={ {''}, {''}, {'(','','','',')'}, {'','(','',')'} } production[""]={ {'+'}, {'-'}, {'*'}, {'/'} } production[""]={ {'math.log'}, {'math.exp'}, {'math.sin'}, {'math.cos'}, {'math.tan'}, } production[""]={ {'0'}, {'1'}, {'2'}, {'3'}, {'4'}, {'5'}, {'6'}, {'7'}, {'8'}, {'9'} } production[""]={ {'0'}, {'1'}, {'2'} } production[""]={ {'high(','',')'}, {'low(','',')'}, {'volume(','',')'}, {'open(','',')'}, {'close(','',')'} } production[""]={ {'','', ''} } production[""]={ {'0.','','',''} } local grammar = Grammar.createGrammar(production, {}) --math.randomseed(0) math.randomseed(os.time()) function randomGenome() local len = math.ceil(math.random() * 300) local genome = {} for i=1,len do table.insert(genome, math.floor(256 * math.random())) end return genome end local g = randomGenome() print(#g, metagrammar:expand(randomGenome())) os.exit(0) function randomPop() local pop = {} for n=1,1000 do table.insert(pop, randomGenome()) end return pop end function evaluate(genome) local s = 'return function(close, volume, open, high, low) return ' .. grammar:expand(genome) .. ' end' -- print(s) local f = assert(loadstring(s))() local cost = 0 for n=1,1000 do local start = math.ceil((#data-300) * math.random()) + 300 local dataView = function(offset, i) return tonumber(string.match(data[1 + start + offset][i], '[^$]+')) end local close = function(offset) return dataView(offset, 2) end local volume = function(offset) return dataView(offset, 3) end local open = function(offset) return dataView(offset, 4) end local high = function(offset) return dataView(offset, 5) end local low = function(offset) return dataView(offset, 6) end ok, y = pcall(f, close, volume, open, high, low) -- if ok and type(y) == 'table' then for k,v in pairs(y) do print(k, v) end end if (not ok) or (y ~= y) then cost = cost + 100 else cost = cost + math.abs(y - high(-30)) end end return -(cost) end local ga = GA.createGA(randomPop(), { evaluate=evaluate, crossover=function(a, b) local crossoverPoint = math.ceil(#a * math.random()) local new = {} for i=1,#b do table.insert(new, (i>=crossoverPoint and b[i]) or a[i]) end return new end, mutate=function(a) local new = {} for i,v in ipairs(a) do new[i] = v end local mutationPoint = math.ceil(#a * math.random()) new[mutationPoint] = math.floor(256 * math.random()) return new end, }) for n=1,100 do print(ga:step()) print(grammar:expand(ga.population[ga.bestMember])) end -- for k,v in ipairs(ga.population) do -- print(k, '(', v[1], v[2], v[3], ')', evaluate(v)) -- end