Welcome to Use RiskQuantLib

RiskQuantLib is a derivative of Quantlib, a famous quantitative library of financial engineering. Unlike QuantLib, however, RiskQuantLib is a scaffolding of financial analysis. RiskQuantLib provides default class of financial instruments and allows you to create new classes you want automatically, given the inheritance rules and other information. It also provides automation building tools to add attributes to classes automatically.

Why Should I Use RiskQuantLib?

  • RiskQuantLib provides with convenient way of object oriented coding in fields of finance.

  • RiskQuantLib is designed on the base of QuantLib, you can use the functions of QuantLib and combine it with RiskQuantLib easily.

  • RiskQuantLib is a scaffolding, which means it creates an independent project for every mission. After creation, RiskQuantLib will be a part of your code. You have full access to your project and can change any source code of RiskQuantLib.

  • RiskQuantLib is suitable for applying to different markets, since all financial instruments are defined by your self.

  • RiskQuantLib allows you to seperate data analysis process. With RiskQuantLib, data storage, data input, data analysis, data output can be operated independently from each other. You don’t have to wait for data input to analysis your data, instead of that, starting coding the analysis logic part before you know the data patterns.

  • RiskQuantLib provides template management function. You can code a template of any mission, such as stock return analysis, and save this template into RiskQuantLib, or share it with other users. Next time you meet with a similar data process problem, you can start a new RiskQuantLib project based on this template.

Who Can Use RiskQuantLib?

RiskQuantLib is designed to allow analyst to code easily, it’s recommanded to be used by financial analyst, students in business school or quant-traders. It’s very useful when dealing with analysis of multiple kinds of financial instruments.

Notice: RiskQuantLib is not designed to dealing with heavy data prcoess mission. RiskQuantLib sacrifice memory and speed to accelerate coding.

Slow Start

Suppose you are employeed by a bank. One day, your bose calls you to his office, he tells you your company want to invest in a new family fund, Archegos, we suppose it is. Your mission, if you accept, is to tell your boss how risky this deal is.

Take adventure after second thought, this is far from recklessness.

After some investigation, you find some data from Bloomberg, however, it only tells you about some stock holdings of the whole fund, like Tencent or Alibaba, etc. The first dataframe you have is like this:

Index

Holding Mkt Value

Stock

0

239018292

TCEHY US Equity

1

710281723

ABC US Equity

2

7497233

HIYJ US Equity

3

179321234

SPACEX US Equity

4

83249

HE US Equity

After this, you decided to download the close price of these stocks over past three years, you get your second dataframe like this:

Date

HIYJ US Equity

U7HJ US Equity

HE US Equity

2020-01-01

23.9

nan

9.8

2020-01-02

nan

12.8

9.5

2020-01-03

21.9

13.1

9.3

2020-01-04

22.1

13.2

9.7

2020-01-05

22.4

12.9

9.8

You decide to calculate the volatility of stocks of Archegos holdings. So you start coding like:

df_stock_holding = pd.read_excel(path_one)
df_stock_close = pd.read_excel(path_two)

If you don’t use RiskQuantLib, you may do it like:

df_std = df_stock_close.std()
std_of_archegos_stock_holdings = df_std[df_stock_holding.columns.to_list()]

Now you are satisfied with what you have done, it seems the risk of stocks can be revealed, at least to some extend. In the afternoon, your boss tells you that he knows Archegos holds two famous fund, called H and JK. He says this is a material non-public information, you may not find net asset value of these two funds by yourself, luckily, your boss has his own way. He gives you the data, which is the third dataframe and it looks like:

Index

Net Asset Value

Fund

0

2.39

H

1

7.22

JK

2

0.98

UIH

Archegos holding shares of these funds are the fourth dataframe, which looks like:

Index

Holding Shares

Fund

0

20000000

H

1

45000000

JK

Your colleague who used to finish a project, focusing on the historical NAV extreme dropdown of all mutual funds, and he tells you that you can use 1.5% as a one-day 99% VaR. So you calculate risk indicator by:

df_fund_holding = pd.read_excel(path_four)
df_fund_nav = pd.read_excel(path_three)

df_fund = pd.merge(df_fund_holding, df_fund_nav, on = 'Fund', how = 'left')
df_fund['Total Holding'] = df_fund['Holding Shares'] * df_fund['Net Asset Value']
df_fund['VaR'] = df_fund['Total Holding'] * 0.015

Now you have used all kinds of information you can get, since Archegos barely publish their holdings. You give your boss the analysis result and waiting to be praised. However, your boss is pissed off. He takes a long time to calm down and tells you that you forget sever important things:

  • The price of stock contains nan, you have to deal with it. And don’t fill nan with last non-nan value, because this will lead to a smaller std than true value.

  • He wants a conclusion of risk of Archegos, not all kinds of risk indicators.

  • The stock price you used is wrong, cause it is a divident-included price.

  • The only reason Archegos buys these two funds is that Archegos can use it as a bridge to buy more shares of stocks, like TCEHY US Equity, this is a trick to use leverage. So you have to take a closer look, dig down to the holdings of these two funds.

Things get to complicated now. You decide to use RiskQuantLib. First of all, you make a dictionary to hold this analysis project, named ‘Archegos_Risk’. Then you open a command terminal, and create a RiskQuantLib project by:

newRQL Archegos_Risk

After this, the dictionary looks like ( In Windows System ):

--Archegos_Risk
  --Cache
  --Data
  --Result
  --RiskQuantLib
  --Src
  --build.bat
  --build.py
  --config.py
  --debug.bat
  --main.py

Open config.py, you edit it and make it looks like:

#!/usr/bin/python
# coding = utf-8

#-|instrument: security, company, index, interest
#-|instrument: bond@security, stock@security, derivative@security, fund@security
#-|instrument: future@derivative, option@derivative

#-|instrument-DefaultInstrumentType: security@Security, company@Company, index@Index, interest@Interest
#-|instrument-DefaultInstrumentType: bond@Bond, stock@Stock, derivative@Derivative, fund@Fund
#-|instrument-DefaultInstrumentType: future@Future, option@Option

#-|attribute: fund.netAssetValue@number, fund.amount@number, fund.varPercentage@number
#-|attribute: stock.mktValue@number, stock.closeSeries@series

Notice that you only add two lines after the default config information. You close this file and build this project in command terminal:

python build.py

After this, you open RiskQuantLib.Instrument.Security.Fund.fund to add class function:

def calVaR(self):
   self.VaR = self.netAssetValue * self.amount * self.varPercentage

You open RiskQuantLib.Instrument.Security.Stock.stock to add class function:

def calVaRPercentage(self):
   from RiskQuantLib.Tool.mathTool import percentageOfSeries
   self.varPercentage = percentageOfSeries(self.closeSeries.dropna().values(),99)

def calVaR(self):
   self.VaR = self.mktValue * self.varPercentage

Notice: All these coding are done before you input your data.

Turn into root path of this project and open main.py, we start analysis:

from RiskQuantLib.Module import *

# Read files
df_stock_holding = pd.read_excel(path_one)
df_stock_close = pd.read_excel(path_two)
df_fund_holding = pd.read_excel(path_four)
df_fund_nav = pd.read_excel(path_three)

# Initialize RQL list object
fund_holdings = fundList()
stock_holdings = stockList()

# Add securities to list
fund_holdings.addFundSeries(df_fund_holding['Fund'],df_fund_holding['Fund'])
stock_holdings.addStockSeries(df_stock_holding['Stock'],df_stock_holding['Stock'])

# Set input
fund_holdings.setNetAssetValue(df_fund_nav['Fund'],df_fund_nav['Net Asset Value'])
fund_holdings.setAmount(df_fund_holding['Fund'],df_fund_holding['Holding Shares'])
stock_holdings.setMktValue(df_stock_holding['Stock'],df_stock_holding['Holding Mkt Value'])
stock_holdings.setCloseSeries(df_stock_close)
[fund.setVarPercentage(0.15) for fund in fund_holdings]

# Calculation
fund_holdings.execFunc('calVaR')
stock_holdings.execFunc('calVaRPercentage')
stock_holdings.execFunc('calVaR')

Now it’s more easy to read and modify, isn’t it? You decide to continue and save your result into excel, so you code:

# Data output
result = stock_holdings + fund_holdings
df_result = pd.DataFrame(result[['code','VaR']])
df_result.to_excel(path)

Till now, the process looks more complicated than a pandas way, however, if you noticed, with RiskQuantLib, data input, data process, data output is independent, change to any of them won’t influence the others. Let’s take a closer look:

Data Input:

main.py:

from RiskQuantLib.Module import *

# Read files
df_stock_holding = pd.read_excel(path_one)
df_stock_close = pd.read_excel(path_two)
df_fund_holding = pd.read_excel(path_four)
df_fund_nav = pd.read_excel(path_three)

# Initialize RQL list object
fund_holdings = fundList()
stock_holdings = stockList()

# Add securities to list
fund_holdings.addFundSeries(df_fund_holding['Fund'],df_fund_holding['Fund'])
stock_holdings.addStockSeries(df_stock_holding['Stock'],df_stock_holding['Stock'])

# Set input
fund_holdings.setNetAssetValue(df_fund_nav['Fund'],df_fund_nav['Net Asset Value'])
fund_holdings.setAmount(df_fund_holding['Fund'],df_fund_holding['Holding Shares'])
stock_holdings.setMktValue(df_stock_holding['Stock'],df_stock_holding['Holding Mkt Value'])
stock_holdings.setCloseSeries(df_stock_close)
[fund.setVarPercentage(0.15) for fund in fund_holdings]

Data Analysis

RiskQuantLib.Instrument.Security.Fund.fund:

def calVaR(self):
   self.VaR = self.netAssetValue * self.amount * self.varPercentage

RiskQuantLib.Instrument.Security.Stock.stock

def calVaRPercentage(self):
   from RiskQuantLib.Tool.mathTool import percentageOfSeries
   self.varPercentage = percentageOfSeries(self.closeSeries.dropna().values(),99)

def calVaR(self):
   self.VaR = self.mktValue * self.varPercentage

main.py

# Calculation
fund_holdings.execFunc('calVaR')
stock_holdings.execFunc('calVaRPercentage')
stock_holdings.execFunc('calVaR')

Data Output

main.py

# Data output
result = stock_holdings + fund_holdings
df_result = pd.DataFrame(result[['code','VaR']])
df_result.to_excel(path)

After all these are done, you can save this project as a template by using terminal command:

saveRQL Archegos_Risk

Next time your boss wants you to analysis another fund, you may start a RiskQuantLib project by calling:

tplRQL Archegos_Risk target_path

This is a simple introduction to RiskQuantLib, about how to start a project, start coding with build, seperate stages of analysis, save project as template and use it again. You may noticed that we have not solved all problems that boss gave to us. More functions can be used to do this. You can refer to RiskQuantLib Class Details for further information.