Ryan Ward d1aa19ef07 initial release
TODO document everything
2018-08-24 17:52:51 -04:00

657 lines
20 KiB
Lua

local https = require("ssl.https")
local bin = require("bin")
local alpha = {}
alpha.APIKey = ""
function string:split( inSplitPattern, outResults)
if not outResults then
outResults = {}
end
local theStart = 1
local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
while theSplitStart do
table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
theStart = theSplitEnd + 1
theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
end
table.insert( outResults, string.sub( self, theStart ) )
return outResults
end
function alpha.setAPIKey(key)
alpha.APIKey = key
end
function alpha.getPhysicalCurrencyList(force)
local dat = ""
if bin.fileExists("PCL.dat") and not force then
dat = bin.load("PCL.dat").data
else
dat = https.request("https://www.alphavantage.co/physical_currency_list/")
bin.new(dat):tofile("PCL.dat")
end
if alpha.pcl then return alpha.pcl end
local c = {}
local lines = dat:lines()
local a,b
for i = 2,#lines-1 do
a,b = lines[i]:match("(.-),(.+)")
c[a]=b
end
alpha.pcl = c
return c
end
function alpha.getDigitalCurrencyList(force)
local dat = ""
if bin.fileExists("DCL.dat") and not force then
dat = bin.load("DCL.dat").data
else
dat = https.request("https://www.alphavantage.co/digital_currency_list/")
bin.new(dat):tofile("DCL.dat")
end
if alpha.dcl then return alpha.dcl end
local c = {}
local lines = dat:lines()
local a,b
for i = 2,#lines-1 do
a,b = lines[i]:match("(.-),(.+)")
c[a]=b
end
alpha.dcl = c
return c
end
function alpha.dataToTable(data)
local c = {}
local order = {}
local lines = data:lines(str)
local tab = {}
local tag = lines[1]:split(",")
for i = 2,#lines-1 do
tab = lines[i]:split(",")
c[tab[1]]={}
for e = 1,#tag do
order[#order+1]=tab[1]
c[tab[1]][tag[e]]=tab[e]
end
end
c.order = order
return c
end
local function simpleparse(command,symbols,outputsize,interval)
local cmd
local data = {}
if type(symbols)=="string" then
symbols = {symbols}
end
if outputsize then
outputsize = "&outputsize="..outputsize
end
local str = ""
if interval then
str = "&interval="..interval
end
for i=1,#symbols do
cmd = "https://www.alphavantage.co/query?function="..command.."&symbol="..symbols[i].."&datatype=csv&apikey="..alpha.APIKey..outputsize..str
dat = https.request(cmd)
if dat:find("Invalid API call") then
return nil, "Invalid API call"
else
data[symbols[i]]=alpha.dataToTable(dat)
end
end
return data
end
-- api.TIME_SERIES_DAILY
function alpha.timeSeriesDaily(symbols,outputsize)
return simpleparse("TIME_SERIES_DAILY",symbols,outputsize)
end
-- api.TIME_SERIES_DAILY_ADJUSTED
function alpha.timeSeriesDailyAdjusted(symbols,outputsize)
return simpleparse("TIME_SERIES_DAILY_ADJUSTED",symbols,outputsize)
end
-- api.TIME_SERIES_WEEKLY
function alpha.timeSeriesWeekly(symbols,outputsize)
return simpleparse("TIME_SERIES_WEEKLY",symbols,outputsize)
end
-- api.TIME_SERIES_WEEKLY_ADJUSTED
function alpha.timeSeriesWeeklyAdjusted(symbols,outputsize)
return simpleparse("TIME_SERIES_WEEKLY_ADJUSTED",symbols,outputsize)
end
-- api.TIME_SERIES_MONTHLY
function alpha.timeSeriesMonthly(symbols,outputsize)
return simpleparse("TIME_SERIES_MONTHLY",symbols,outputsize)
end
-- api.TIME_SERIES_MONTHLY_ADJUSTED
function alpha.timeSeriesMonthlyAdjusted(symbols,outputsize)
return simpleparse("TIME_SERIES_MONTHLY_ADJUSTED",symbols,outputsize)
end
-- api.TIME_SERIES_INTRADAY
local _interval = {
["1min"]=true,
["5min"]=true,
["15min"]=true,
["30min"]=true,
["60min"]=true,
["daily"]=true,
["monthly"]=true,
["weekly"]=true,
}
function alpha.timeSeriesIntraday(symbols,interval,outputsize)
interval = interval or "5min"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
return simpleparse("TIME_SERIES_INTRADAY",symbols,outputsize,interval)
end
-- api.CURRENCY_EXCHANGE_RATE
function alpha.currencyExchangeRate(from,to)
local dat = https.request("https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency="..from.."&to_currency="..to.."&apikey="..alpha.APIKey)
if dat:find("Invalid API call") then
return nil, "Invalid API call"
else
local c = {}
local lines = dat:lines()
local var,val
for i = 3,#lines-2 do
var,val = lines[i]:match("%d-%. (.-)\": \"(.-)\"")
c[(var:gsub("Currency.",""))]=tonumber(val) or val
end
return c
end
end
local function simpleFXParse(cmd,from,to,interval,outputsize)
if outputsize then
outputsize = "&outputsize="..outputsize
end
interval = interval or ""
print("https://www.alphavantage.co/query?function="..cmd.."&from_symbol="..from.."&to_symbol="..to..interval.."&apikey="..alpha.APIKey.."&datatype=csv"..outputsize)
local dat = https.request("https://www.alphavantage.co/query?function="..cmd.."&from_symbol="..from.."&to_symbol="..to..interval.."&apikey="..alpha.APIKey.."&datatype=csv"..outputsize)
if dat:find("Invalid API call") then
return nil, "Invalid API call"
else
local data = alpha.dataToTable(dat)
data.From = from
data.To = to
return data
end
end
-- api.FX_INTRADAY
function alpha.currencyExchangeIntraday(from,to,interval,outputsize)
interval = interval or "5min"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
return simpleFXParse("FX_INTRADAY",from,to,"&interval="..interval,outputsize)
end
-- api.FX_DAILY
function alpha.currencyExchangeDaily(from,to,outputsize)
return simpleFXParse("FX_DAILY",from,to,nil,outputsize)
end
-- api.FX_WEEKLY
function alpha.currencyExchangeWeekly(from,to,outputsize)
return simpleFXParse("FX_WEEKLY",from,to)
end
-- api.FX_MONTHLY
function alpha.currencyExchangeMonthly(from,to,outputsize)
return simpleFXParse("FX_MONTHLY",from,to)
end
local function simpleDigitalParse(command,symbols,market)
local data = {}
if type(symbols)=="string" then
symbols = {symbols}
end
for i=1,#symbols do
dat = https.request("https://www.alphavantage.co/query?function="..command.."&symbol="..symbols[i].."&market="..market.."&datatype=csv&apikey="..alpha.APIKey)
if dat:find("Invalid API call") then
return nil, "Invalid API call"
else
data[symbols[i]]=alpha.dataToTable(dat)
end
end
return data
end
-- api.DIGITAL_CURRENCY_INTRADAY
function alpha.digitalCurrencyIntraday(symbols,market)
return simpleDigitalParse("DIGITAL_CURRENCY_INTRADAY",symbols,market)
end
-- api.DIGITAL_CURRENCY_DAILY
function alpha.digitalCurrencyDaily(symbols,market)
return simpleDigitalParse("DIGITAL_CURRENCY_DAILY",symbols,market)
end
-- api.DIGITAL_CURRENCY_WEEKLY
function alpha.digitalCurrencyWeekly(symbols,market)
return simpleDigitalParse("DIGITAL_CURRENCY_WEEKLY",symbols,market)
end
-- api.DIGITAL_CURRENCY_MONTHLY
function alpha.digitalCurrencyMonthly(symbols,market)
return simpleDigitalParse("DIGITAL_CURRENCY_MONTHLY",symbols,market)
end
alpha.Close = "close"
alpha.Open = "open"
alpha.High = "high"
alpha.Low = "low"
local function technicalParsers(cmd,symbol,interval,time_period,series_type,t)
local extras = ""
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
for i,v in pairs(t or {}) do
extras=extras.."&"..i.."="..v
end
local data = https.request("https://www.alphavantage.co/query?function="..cmd.."&datatype=csv&symbol="..symbol.."&interval="..interval.."&time_period="..time_period.."&series_type="..series_type.."&apikey="..alpha.APIKey..extras)
if data:find("Invalid API call") then
return nil, "Invalid API call"
end
return alpha.dataToTable(data)
end
local function technicalParsers2(cmd,symbol,t)
local extras = ""
for i,v in pairs(t or {}) do
extras=extras.."&"..i.."="..v
end
local c = "https://www.alphavantage.co/query?function="..cmd.."&datatype=csv&symbol="..symbol.."&apikey="..alpha.APIKey..extras
local data = https.request(c)
if data:find("Invalid API call") then
return nil, "Invalid API call"
end
return alpha.dataToTable(data)
end
-- api.SMA
function alpha.getSMA(symbol,interval,time_period,series_type)
return technicalParsers("SMA",symbol,interval,time_period,series_type)
end
-- api.EMA
function alpha.getEMA(symbol,interval,time_period,series_type)
return technicalParsers("EMA",symbol,interval,time_period,series_type)
end
-- api.WMA
function alpha.getWMA(symbol,interval,time_period,series_type)
return technicalParsers("WMA",symbol,interval,time_period,series_type)
end
-- api.DEMA
function alpha.getDEMA(symbol,interval,time_period,series_type)
return technicalParsers("DEMA",symbol,interval,time_period,series_type)
end
-- api.TEMA
function alpha.getTEMA(symbol,interval,time_period,series_type)
return technicalParsers("TEMA",symbol,interval,time_period,series_type)
end
-- api.TRIMA
function alpha.getTRIMA(symbol,interval,time_period,series_type)
return technicalParsers("TRIMA",symbol,interval,time_period,series_type)
end
-- api.KAMA
function alpha.getKAMA(symbol,interval,time_period,series_type)
return technicalParsers("KAMA",symbol,interval,time_period,series_type)
end
-- api.MAMA
function alpha.getMAMA(symbol,interval,time_period,series_type,fastlimit,slowlimit)
return technicalParsers("MAMA",symbol,interval,time_period,series_type,{
fastlimit=fastlimit,
slowlimit=slowlimit
})
end
-- api.T3
function alpha.getT3(symbol,interval,time_period,series_type)
return technicalParsers("T3",symbol,interval,time_period,series_type)
end
-- api.MACD
--fastperiod,slowperiod,signalperiod
function alpha.getMACD(symbol,interval,time_period,series_type,t)
return technicalParsers("MACD",symbol,interval,time_period,series_type,t)
end
-- api.MACDEXT
--fastperiod,slowperiod,signalperiod,fastmatype,slowmatype,signalmatype
function alpha.getMACDEXT(symbol,interval,time_period,series_type,t)
return technicalParsers("MACDEXT",symbol,interval,time_period,series_type,t)
end
-- api.STOCH
--fastkperiod,slowkperiod,slowdperiod,slowkmatype,slowdmatype
function alpha.getSTOCH(symbol,t)
return technicalParsers2("STOCH",symbol,t)
end
-- api.STOCHF
function alpha.getSTOCHF(symbol,t)
return technicalParsers2("STOCHF",symbol,t)
end
-- api.RSI
function alpha.getRSI(symbol,interval,time_period,series_type)
return technicalParsers("RSI",symbol,interval,time_period,series_type)
end
-- api.STOCHRSI
function alpha.getSTOCHRSI(symbol,interval,time_period,series_type)
return technicalParsers("STOCHRSI",symbol,interval,time_period,series_type)
end
-- api.WILLR
function alpha.getWILLR(symbol,interval,time_period,t)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("WILLR",symbol,t)
end
-- api.ADX
function alpha.getADX(symbol,interval,time_period,t)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("ADX",symbol,t)
end
-- api.ADXR
function alpha.getADXR(symbol,interval,time_period,t)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("ADXR",symbol,t)
end
-- api.APO
function alpha.getAPO(symbol,interval,time_period,series_type,t)
return technicalParsers("APO",symbol,interval,time_period,series_type,t)
end
-- api.PPO
function alpha.getPPO(symbol,interval,time_period,series_type,t)
return technicalParsers("PPO",symbol,interval,time_period,series_type,t)
end
-- api.MOM
function alpha.getMOM(symbol,interval,time_period,series_type)
return technicalParsers("MOM",symbol,interval,time_period,series_type)
end
-- api.BOP
function alpha.getBOP(symbol,interval)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
return technicalParsers2("BOP",symbol,t)
end
-- api.CCI
function alpha.getCCI(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("CCI",symbol,t)
end
-- api.CMO
function alpha.getCMO(symbol,interval,time_period,series_type)
return technicalParsers("CMO",symbol,interval,time_period,series_type)
end
-- api.ROC
function alpha.getROC(symbol,interval,time_period,series_type)
return technicalParsers("ROC",symbol,interval,time_period,series_type)
end
-- api.ROCR
function alpha.getROCR(symbol,interval,time_period,series_type)
return technicalParsers("ROCR",symbol,interval,time_period,series_type)
end
-- api.AROON
function alpha.getAROON(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("AROON",symbol,t)
end
-- api.AROONOSC
function alpha.getAROONOSC(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("AROONOSC",symbol,t)
end
-- api.MFI
function alpha.getMFI(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("MFI",symbol,t)
end
-- api.TRIX
function alpha.getTRIX(symbol,interval,time_period,series_type)
return technicalParsers("TRIX",symbol,interval,time_period,series_type)
end
-- api.ULTOSC
function alpha.getULTOSC(symbol,interval,t)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("ULTOSC",symbol,t)
end
-- api.DX
function alpha.getDX(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("DX",symbol,t)
end
-- api.MINUS_DI
function alpha.getMinusDI(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("MINUS_DI",symbol,t)
end
-- api.PLUS_DI
function alpha.getPlusDI(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("PLUS_DI",symbol,t)
end
-- api.MINUS_DM
function alpha.getMinusDM(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("MINUS_DM",symbol,t)
end
-- api.PLUS_DM
function alpha.getPlusDM(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("PLUS_DM",symbol,t)
end
-- api.BBANDS
function alpha.getBBands(symbol,interval,time_period,series_type,t)
return technicalParsers("BBANDS",symbol,interval,time_period,series_type,t)
end
-- api.MIDPOINT
function alpha.getMidpoint(symbol,interval,time_period,series_type)
return technicalParsers("MIDPOINT",symbol,interval,time_period,series_type)
end
-- api.MIDPRICE
function alpha.getMidprice(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("MIDPRICE",symbol,t)
end
-- api.SAR
function alpha.getSAR(symbol,interval,t)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
return technicalParsers2("SAR",symbol,t)
end
-- api.TRANGE
function alpha.getTRange(symbol,interval)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
return technicalParsers2("TRANGE",symbol,t)
end
-- api.ATR
function alpha.getATR(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("ATR",symbol,t)
end
-- api.NATR
function alpha.getNATR(symbol,interval,time_period)
t = t or {}
interval = interval or "monthly"
time_period=time_period or "60"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
t.time_period=time_period
return technicalParsers2("NATR",symbol,t)
end
-- api.AD
function alpha.getAD(symbol,interval)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
return technicalParsers2("AD",symbol,t)
end
-- api.ADOSC
function alpha.getADOSC(symbol,interval)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
return technicalParsers2("ADOSC",symbol,t)
end
-- api.OBV
function alpha.getOBV(symbol,interval)
t = t or {}
interval = interval or "monthly"
if not _interval[interval] then
return nil,interval.." is not a supported interval that can be used"
end
t.interval=interval
return technicalParsers2("OBV",symbol,t)
end
-- api.HT_TRENDLINE
function alpha.getHTTrendLine(symbol,interval,time_period,series_type,t)
return technicalParsers("HT_TRENDLINE",symbol,interval,time_period,series_type,t)
end
-- api.HT_SINE
function alpha.getHTSine(symbol,interval,time_period,series_type,t)
return technicalParsers("HT_SINE",symbol,interval,time_period,series_type,t)
end
-- api.HT_TRENDMODE
function alpha.getHTTrendMode(symbol,interval,time_period,series_type,t)
return technicalParsers("HT_TRENDMODE",symbol,interval,time_period,series_type,t)
end
-- api.HT_DCPERIOD
function alpha.getHTDCPeriod(symbol,interval,time_period,series_type,t)
return technicalParsers("HT_DCPERIOD",symbol,interval,time_period,series_type,t)
end
-- api.HT_DCPHASE
function alpha.getHTDCPhase(symbol,interval,time_period,series_type,t)
return technicalParsers("HT_DCPHASE",symbol,interval,time_period,series_type,t)
end
-- api.HT_PHASOR
function alpha.getHTPhasor(symbol,interval,time_period,series_type,t)
return technicalParsers("HT_PHASOR",symbol,interval,time_period,series_type,t)
end
-- api.SECTOR
function alpha.getSectorPreformance()
local raw = https.request("https://www.alphavantage.co/query?function=SECTOR&apikey="..alpha.APIKey)
raw=raw:gsub(" ","")
local c = {}
for section,data in raw:gmatch([["(.-)": {.(.-).}]]) do
_section,desc = section:match("(.-): (.+)")
if _section then
_section=_section:gsub(" ","")
section = _section
c[section]={}
c[section].Desc = desc
else
c[section]={}
end
for var,val in data:gmatch([["(.-)": "(.-)",?]]) do
c[section][var]=val
end
end
return c
end
return alpha