UNPKG

fme-free-barchart

Version:

API for fetching data from the Free Barchart API

185 lines (151 loc) 6.38 kB
import {Log} from "fme-logger"; var L = new Log("FreeBarchart"); import * as _m from "moment-timezone"; import * as request from "request-promise-native"; import {FmeQuote} from "fme-quotes-models"; interface EsQuote { } interface History { } function convert (x:any,type:string,interval:number) { var obj = new FmeQuote(); obj.symbol = x.symbol.toUpperCase(); obj.YYYYMMDD = _m(x.timestamp).format("YYYYMMDD"); obj.timeHHMM = _m(x.timestamp).format("HHmm"); obj.time = _m(x.timestamp).hours()*60+_m(x.timestamp).minutes(); obj.timestamp = x.timestamp; obj.open = x.open; obj.close = x.close; obj.high = x.high; obj.low = x.low; obj.avg = (x.open+x.close+x.high+x.low)/4; obj.volume = x.volume; obj.source = "barchart-free"; obj.decimalPoints = 2; obj.interval = interval; obj.type = type; return obj } export class FreeBarchart { version = "1.0.0"; host = "marketdata.websol.barchart.com"; endpoint = "getHistory.json"; // symbol = "ES*1"; symbol = "SPY"; type = "minutes"; types = ["ticks", "minutes", "nearbyMinutes", "formTMinutes", "daily", "dailyNearest", "dailyContinue", "weekly", "weeklyNearest", "weeklyContinue", "monthly", "monthlyNearest", "monthlyContinue", "quarterly", "quarterlyNearest", "quarterlyContinue", "yearly", "yearlyNearest", "yearlyContinue"]; typesSingleDay = ["ticks","minutes","nearbyMinutes","formTMinutes"]; interval = 1; startTime = 9*60 + 30; // default startTime == 9:30; endTime = 16*60 + 0; // default endTime = 4pm; targetDate = new Date(); // // @KEY = FREE BARCHART KEY STRING // @SYMBOL = BARCHART SYMBOL // @FRAME = TIMEFRAME = "minute","day","week" // @Interval = number (1,2,3) (combines with FRAME to complete the reqeust); // constructor(private key:string,symbol:string,frame:string,interval:number,targetDate:Date,startTime?:number,endTime?:number) { this.symbol = symbol; // // => convert futures contract to dated contract based on target date // if (this.symbol.toLowerCase().indexOf("_f")> -1) { var contract = new ContractConversion() var expiry = 3; if (symbol.toLowerCase().indexOf("cl")> -1) expiry = 1; this.symbol = this.symbol.toLowerCase().replace("_f",contract.findCode(targetDate,expiry)) } this.type = frame.toLowerCase().trim(); if (startTime) this.startTime == startTime; if (endTime) this.endTime == endTime; this.targetDate = targetDate; if (this.types.indexOf(this.type) == -1 ) { L.error("Invalid type passed",this.types,"valid types are",JSON.stringify(this.types)) return; } if (!interval) this.interval = 1; else this.interval = interval;; } getDailyMinutes = async () => { var type = this.type.trim().toLowerCase(); var symbol = this.symbol.trim().toLowerCase(); var startDate = _m(this.targetDate).format("YYYYMMDD"); var req = "/"+this.endpoint+"?key="+this.key+"&symbol="+this.symbol+"&type="+type+"&startDate="+startDate+"&interval="+this.interval; var fullUrl = "http://"+this.host+req; L.info("requesting:",fullUrl); try { var results = await request(fullUrl) var rtn = JSON.parse(results).results; if (!rtn) { L.info("barchart did not return a value for date",startDate) return null; } }catch(err) { L.error(err,results); return } L.info("Rtn is",rtn.length,rtn[rtn.length-1]); var filter:FmeQuote[] = []; if (this.typesSingleDay.indexOf(type) > -1) { filter = rtn.filter((x:any) =>{return _m(x.timestamp).format("YYYYMMDD") == startDate } ).map((a:any)=>{ return convert(a,type,this.interval)} ) as FmeQuote[]; } else { filter = rtn.filter.map((a:any)=>{ return convert(a,type,this.interval)} ) as FmeQuote[]; } // L.info("filter length is",filter.length,filter[0],filter[filter.length-1]); // return filter.filter((a) => {return a.time >= this.startTime && a.time <= this.endTime}); return filter.map( (a:any) => {return convert(a,type,this.interval)} ) } } export class Conversion { inputSymbol:string = "SPY"; symbol: string = "spy"; exchange: string = "nyse"; timeAdjust?:number = 0; expiryLength? = 3 } export class ContractConversion { codes = ["F","G","H","J","K","M","N","Q","U","V","X","Z"]; rollOffset = 8 ; // number of days offset from expiration the roll is. // // => find codes // Date: date to find code for // Length: Number of Months between contract roll, only supports monthly (1) or quarterly(3); // findCode = (date:Date,length:number) => { if (length == 1) { if (_m(date).date() > 20) offset = 2; else offset = 2; var month = _m(date).month()+offset; return this.codes[month]+_m(date).format("YY"); } if(length == 3) { var quarter = _m(date).quarter();; // quarter to find contract L.info("We are in this quarter",quarter); // // add either 2 or 5 to this number to get the contract // add 2 if the current date is before the expiration + rolloffset, else add 3. // var startOfMonth = _m(date).startOf("quarter").add(2,"months").clone(); var today = startOfMonth.day(); if (today == 6) var inc = 3 else inc = 2; var expiration = startOfMonth.day(5).add(inc,"weeks"); var rollover = expiration.clone().subtract(this.rollOffset,"days"); L.info("Date",_m(date).format("YYYYMMDD"),"rollover",rollover.format("YYYYMMDD")); if ( date >= rollover.toDate()) var offset = quarter*3+2; else offset=quarter*3-1; // // => take care of annual roll at the end of the year! // var annualOffset = 0; if (offset > 11) { offset = offset - 12; annualOffset = 1; } L.info("expiration is",expiration.format("YYYYMMDD"),"roll over is",rollover.format("YYYYMMDD"),"offset is",offset) return this.codes[offset]+_m(date).add(annualOffset,"years").format("YY"); } } }