Program : nimFinLib
Status : Development
License : MIT opensource
Version : 0.2.x
Compiler : nim 0.11.3
Description : A basic library for financial calculations with Nim
Yahoo historical stock data
Yahoo additional stock data
Yahoo current stock quotes
Yahoo forex rates
Dataframe like structure for easy working with historical data and dataseries
Returns calculations
Ema calculation
Date manipulations
Data display procs
Documention was created with : nim doc nimFinLib
Project : https://github.com/qqtop/NimFinLib
Tested on : Linux
ProjectStart: 2015-06-05
ToDo : Ratios , Covariance , Correlation
Programming : qqTop
Contributors: reactorMonk
Requires : strfmt,random modules and statistics.nim
Notes : it is assumed that terminal color is black background
and white text. Other color schemes may not show all output.
For comprehensive tests and usage see nimFinT5.nim
Installation: git clone https://github.com/qqtop/NimFinLib.git
or
nimble install nimFinLib
Types
Pf* = object pf*: seq[Nf] ## pf holds all Nf type portfolios for an account
- Pf type holds all portfolios similar to a master account portfolios are Nf objects
Nf* {.inheritable.} = object nx*: string ## nx holds portfolio name e.g. MyGetRichPortfolio dx*: seq[Df] ## dx holds all stocks with historical data
- Nf type holds one portfolio with all relevant historic stocks data
Df* {.inheritable.} = object of Nf stock*: string ## yahoo style stock code date*: seq[string] open*: seq[float] high*: seq[float] low*: seq[float] close*: seq[float] vol*: seq[float] ## volume adjc*: seq[float] ## adjusted close price ro*: seq[Runningstat] ## RunningStat for open price rh*: seq[Runningstat] ## RunningStat for high price rl*: seq[Runningstat] ## RunningStat for low price rc*: seq[Runningstat] ## RunningStat for close price rv*: seq[Runningstat] ## RunningStat for volume price rca*: seq[Runningstat] ## RunningStat for adjusted close price
- Df type holds individual stocks history data and RunningStat for ohlcva columns even more items may be added like full company name etc in the future items are stock code, ohlcva, rc and rca .
Qf* {.inheritable.} = object price*: float change*: float volume*: float avgdailyvol*: float market*: string marketcap*: string bookvalue*: float ebitda*: string dividendpershare*: float dividendperyield*: float earningspershare*: float week52high*: float week52low*: float movingavg50day*: float movingavg200day*: float priceearingratio*: float priceearninggrowthratio*: float pricesalesratio*: float pricebookratio*: float shortratio*: float
- Qf type holds additional stock data and statistics as currently available from yahoo
Ts* {.inheritable.} = object dd*: seq[string] tx*: seq[float]
- Ts type is a simple timeseries object which can hold one column of any OHLCVA data
Cf* {.inheritable.} = object cu*: seq[string] ra*: seq[float]
- Cf type is a simple object to hold current currency data
Procs
proc timeSeries*[T](self: T; ty: string): Ts
-
timeseries returns a Ts type date and one data column based on ty selection input usually is a Df object and a string , if a string is in ohlcva the relevant series will be extracted from the Df object
usage exmple :
timeseries(myDfObject,"o")
this would return dates in dd and open prices in ts
proc showTimeSeries*(ats: Ts; header, ty: string; N: int)
-
showTimeseries takes a Ts object as input as well as a header string for the data column , a string which can be one of head,tail,all and N for number of rows to display usage :
showTimeseries(myTimeseries,myHeader,"head|tail|all",rows)
Example
# show adj. close price , 5 rows head and tail 372 days apart var myD =initDf() myD = getSymbol2("AAPL",minusdays(getDateStr(),372),getDateStr()) var mydT = timeseries(myD,"a") # adjusted close echo() showTimeSeries(mydT,"AdjClose","head",5) showTimeSeries(mydT,"AdjClose","tail",5)
proc initPf*(): PF
-
initPf
init a new empty account object
var myAccount = initPf()
proc initNf*(): Nf
-
initNf
init a new empty portfolio object
var myETFportfolio = initNf()
proc initDf*(): Df
-
initDf
init stock data object
var mystockData = initDf()
proc initCf*(): Cf
-
initCf
init a Cf object to hold basic forex data
var myForex = initCf()
proc initTs*(): Ts
-
initTs
init a timeseries object
proc initPool*(): seq[Df]
-
initPool
init pools , which are sequences of Df objects used in portfolio building
var mystockPool = initPool()
proc getTerminalWidth*(): int
-
getTerminalWidth
utility to easily draw correctly sized lines on linux terminals
and get linux terminal width
for windows this currently is set to terminalwidth 80
echo "Terminalwidth : ",tw echo aline
tw and aline are exported but of course you also can do
var mytermwidth = getTerminalWidth() echo repeat("*",mytermwidth)
in case you want to use another line building char
proc decho*(z: int)
-
decho
blank lines creator
decho(10)
to create 10 blank lines
proc getCurrentQuote*(stcks: string): string
-
getCurrentQuote
gets the current price/quote from yahoo for 1 stock code
proc buildStockString*(apf: Nf): string
-
buildStockString
Produce a string of one or more stock codes coming from a Nf object
proc buildStockString*(adf: seq[Df]): string
-
buildStockString
Produce a string of one or more stock codes coming from a pool Df object
proc showCurrentIndexes*(idxs: string) {.discardable.}
-
showCurrentIndexes
callable display routine for currentIndexes
proc showCurrentIndexes*(adf: seq[Df]) {.discardable.}
-
showCurrentIndexes
callable display routine for currentIndexes with a pool object passed in
proc showCurrentStocks*(apf: Nf) {.discardable.}
-
showCurrentStocks
callable display routine for currentStocks with Nf portfolio object passed in
showCurrentStocks(myAccount.Portfolio[0])
This means get all stock codes of the first portfolio in myAccount
Note : Yahoo servers maybe down sometimes which will make this procs fail.
Just wait a bit and try again. Stay calm ! Do not panic !
for full example see nimFinT5.nim
proc showCurrentStocks*(stcks: string) {.discardable.}
-
showCurrentStocks
callable display routine for currentStocks with stockstring passed in
showCurrentStocks("IBM+BP.L+0001.HK") decho(2)
Note : Yahoo servers maybe down sometimes which will make this procs fail.
Just wait a bit and try again. Stay calm ! Do not panic !
proc day*(aDate: string): string
-
day
get day substring from a yyyy-MM-dd date string
Format dd
proc ymonth*(aDate: string): string
-
ymonth
yahoo month starts with 00 for jan
Format MM
not exported and only used internally for yahoo url setup
proc month*(aDate: string): string
-
month
get month substring from a yyyy-MM-dd date string
Format MM
proc year*(aDate: string): string
-
year
get year substring from a yyyy-MM-dd date string
Format yyyy
proc validdate*(adate: string): bool
proc intervalsecs*(startDate, endDate: string): float
- interval procs returns time elapsed between two dates in secs,hours etc.
proc intervalmins*(startDate, endDate: string): float
proc intervalhours*(startDate, endDate: string): float
proc intervaldays*(startDate, endDate: string): float
proc intervalweeks*(startDate, endDate: string): float
proc intervalmonths*(startDate, endDate: string): float
proc intervalyears*(startDate, endDate: string): float
proc compareDates*(startDate, endDate: string): int
proc sleepy*[T: float | int](s: T)
proc plusDays*(aDate: string; days: int): string
-
plusDays
adds days to date string of format yyyy-MM-dd or result of getDateStr()
and returns a string of format yyyy-MM-dd
the passed in date string must be a valid date or an error message will be returned
proc minusDays*(aDate: string; days: int): string
-
minusDays
subtracts days from a date string of format yyyy-MM-dd or result of getDateStr()
and returns a string of format yyyy-MM-dd
the passed in date string must be a valid date or an error message will be returned
proc getSymbol2*(symb, startDate, endDate: string): Df
-
getSymbol2
the work horse proc for getting yahoo data in csv format
and then to parse into a Df object
proc getSymbol3*(symb: string): Qf
-
getSymbol3
additional data as provided by yahoo for a stock
data returned is inside an Qf object with following fields and types
the reason for string types in marketcap and ebitda is yahoo returning
numbers shortened with B for billions etc.
not all data may be available for stocks or even maybe incorrect.
so use with care.
price* : float
change* : float
volume* : float
avgdailyvol* : float
market* : string
marketcap* : string
bookvalue* : float
ebitda* : string
dividendpershare* : float
dividendperyield* : float
earningspershare* : float
week52high* : float
week52low* : float
movingavg50day* : float
movingavg200day* : float
priceearingratio* : float
priceearninggrowthratio* : float
pricesalesratio* : float
pricebookratio* : float
shortratio* : float
proc showHistData*(adf: Df; n: int)
-
showhistData
Show n recent rows historical stock data
proc showHistData*(adf: Df; s: string; e: string)
-
showhistData
show historical stock data between 2 dates
dates must be of format yyyy-MM-dd
proc last*[T](self: seq[T]): T
-
Various data navigation routines
first,last,head,tail
last means most recent row
proc first*[T](self: seq[T]): T
- first means oldest row
proc tail*[T](self: seq[T]; n: int): seq[T]
- tail means most recent rows
proc head*[T](self: seq[T]; n: int): seq[T]
- head means oldest rows
proc lagger*[T](self: T; days: int): T
-
lagger
often we need a timeseries off by x days
this functions provides this
proc dailyReturns*(self: seq[float]): seq
-
dailyReturns
daily returns calculation gives same results as dailyReturns in R / quantmod
proc showDailyReturnsCl*(self: Df; N: int)
-
showdailyReturnsCl
display returns based on close price
formated output to show date and returns columns
proc showDailyReturnsAdCl*(self: Df; N: int)
-
showdailyReturnsAdCl
returns based on adjusted close price
formated output to only show date and returns
proc sumDailyReturnsCl*(self: Df): float
-
sumdailyReturnsCl
returns sum based on close price
proc sumDailyReturnsAdCl*(self: Df): float
-
sumdailyReturnsAdCl
returns sum based on adjc
proc statistics*(x: Runningstat)
-
statistics
display statistsics output of a runningstat object
proc showStatistics*(z: Df)
-
showStatistics
shows all statistics from a Df objects ohlcva columns
proc showStatisticsT*(z: Df)
-
showStatisticsT
shows all statistics from a Df objects ohlcva columns
transposed display , needs full terminal width
proc ema*(dx: Df; N: int): Ts
-
ema
exponential moving average based on close price
returns a Ts object loaded with date,ema pairs
calling with Df object and number of days for moving average
results match R quantmod/TTR
proc showEma*(emx: Ts; N: int)
-
showEma
convenience proc to display ema series with dates
input is a ema series Ts object and rows to display
latest data is on top
proc getCurrentForex*(curs: seq[string]): Cf
-
getCurrentForex
get the latest yahoo exchange rate info for a currency pair
e.g EURUSD , JPYUSD ,GBPHKD
var curs = getCurrentForex(@["EURUSD","EURHKD"]) echo() echo "Current EURUSD Rate : ","{:<8}".fmt(curs.ra[0]) echo "Current EURHKD Rate : ","{:<8}".fmt(curs.ra[1]) echo()
proc showCurrentForex*(curs: seq[string])
-
showCurrentForex
a convenience proc to display exchange rates
showCurrentForex(@["EURUSD","GBPHKD","CADEUR","AUDNZD"]) decho(3)
proc showDfTable*(apfdata: Nf)
-
showDfTable
a convenience prog to display the data part of a Nf object
for usage example see nimFinT3
proc showQftable*(a: Qf)
-
showQftable
shows all items of a Qf object
proc presentValue*[T](FV: T; r: T; m: int; t: int): float
-
presentValue
Present Value Calculation for a Lump Sum Investment
- Future Value (FV)
- is the future value sum of an investment that you want to find a present value for
- Number of Periods (t)
- commonly this will be number of years but periods can be any time unit. Use int or floats for partial periods such as months for example, 7.5 years is 7 yr 6 mo.
- Interest Rate (R)
- is the annual nominal interest rate or "stated rate" in percent. r = R/100, the interest rate in integer or floats
- Compounding (m)
- is the number of times compounding occurs per period. If a period is a year then annually=1, quarterly=4, monthly=12, daily = 365, etc.
- Rate (i)
- i = (r/m); interest rate per compounding period.
- Total Number of Periods (n)
- n = mt; is the total number of compounding periods for the life of the investment.
- Present Value (PV)
- the calculated present value of your future value amount
From http://www.CalculatorSoup.com - Online Calculator Resource.
var FV : float = 10000 var PV : float = 0.0 var r : float = 0.0625 var m : int = 2 var t : int = 12 PV = presentValue(FV,r,m,t) echo PV
proc presentValue*(FV: float; r: float; m: float; t: float): float
-
presentValue
Present Value Calculation for a Lump Sum Investment
PV = presentValue(FV,0.0925,2.0,12.0) echo PV
proc presentValueFV*(FV: float; i: float; n: int): float
-
presentValueFV
the present value of a future sum at a periodic interest rate i where n is the number of periods in the future.
PV = presentValueFV(FV,0.0625,10) echo PV
proc presentValueFV*(FV: float; i: float; n: float): float
-
PV = presentValueFV(FV,0.0625,20.5) echo PV
proc rainbow*(astr: string)
-
rainbow
random multi colored string
rainbow("Sparkling string display !") decho(2)
proc handler*() {.noconv.}
-
handler
experimental
this runs if ctrl-c is pressed
and provides some feedback upon exit
import nimFinLib # get the latest delayed quotes for your stock # press ctrl-c to exit # setControlCHook(handler) # auto registered exit handler while true : showCurrentStocks("IBM+AAPL+BP.L") sleepy(5)
proc logisticf*(z: float): float
-
logisticf
maps the input z to an output between 0 and 1
proc logisticf_derivative*(z: float): float
-
logisticf_derivative
returns derivative of logisticf for gradient solutions
proc doFinish*()
-
doFinish
a end of program routine which displays some information
can be changed to anything desired
Templates
template msgg*(code: stmt): stmt {.immediate.}
-
msgX templates convenience templates for colored text output the assumption is that the terminal is white text and black background naming of the templates is like msg+color so msgy => yellow msg+color+b turns on the bright flag
msgg() do : echo "How nice, it's in green"
template msggb*(code: stmt): stmt {.immediate.}
-
msggb
msggb() do : echo "How nice, it's in bright green"
template msgy*(code: stmt): stmt {.immediate.}
template msgyb*(code: stmt): stmt {.immediate.}
template msgr*(code: stmt): stmt {.immediate.}
template msgrb*(code: stmt): stmt {.immediate.}
template msgc*(code: stmt): stmt {.immediate.}
template msgcb*(code: stmt): stmt {.immediate.}
template msgw*(code: stmt): stmt {.immediate.}
template msgwb*(code: stmt): stmt {.immediate.}
template msgb*(code: stmt): stmt {.immediate.}
template hdx*(code: stmt): stmt {.immediate.}
-
hdx
hdx is used for headers to make them stand out
it puts the text between 2 horizontal lines
template withFile*(f: expr; filename: string; mode: FileMode; body: stmt): stmt {. immediate.}
-
withFile
file open close utility template
let curFile="notes.txt" # some file withFile(txt, curFile, fmRead): while true : try: stdout.writeln(txt.readLine()) # do something with the lines except: break echo()