Background
This page introduces a model of high speed Internet application for financial industry through developing a prototype of server-client application over the Internet. The client is single page application (SPA) with React.js and the server is developed from scratch based on C++. The server-client communication is WebSocket. Web Socket and C++ application enables to handle high volume transaction over the Internet. The application is just a prototype application so that it cannot support real business but it is enough to examine the feasibility to use this model in the real world. The supposed business is OTC option trade for client and trader communication over the Internet. Client can send a RFQ (Request For Quotation), then trader can response a quote for this. Client can oder or reject their quote, then trader can execute a order from client. The sequence sequence is below.
The real business needs bid/offer volatility but to make it easier to examine it from technology point of view, bid/offer volatility quote is not supported. Through developing this prototype application, we will examine not only technologies but also development process. What is necessary to increase quality but reduce cost.
Application Design
The following diagram shows component diagram for this application. The client side is composed of React.js, Redux, and Redux Thunk middleware on the web browser. The client application is single page application (SPA) with MVVM - Model-View-ViewModel software architecture. It reduces communication overhead between server and client comparing with HTTP GET/PUT method, also it enables asynchronous communication without polling. The React enable quick draw with virtual DOM. The Redux-Thunk middleware enables asynchronize access between React and Redux. The server side is composed of MariaDB, libwebsockets, and QuantLib. The server needs to use QuantLib to calculate option price and greeks and this library has only C API, so that to make it simple, the server is developed base on C++. The database engine is MariaDB because UPDATE overwrites existing record if the record size is same. This behavior (overwrite) is faster than UPDATE which seeks new memory area like PostgreSQL.
Database Design
Financial system requires performance. The design policy is following.
The advantage for this policy is that there are two types of database engine, for example postgress SQL and Maria DB. Both database engines are very popular open source software. The difference is that update operation. Postgress SQL reallocates record space for update operation but Maria DB is different. The Maria DB allocates record space if record size is variable. If it is fixed record size, it overwrite a record when it is update operation. That makes better performance because it does not need to search free space in the disc. Off cause some of engine supports pre allocation model. Even though, that will allocation always as a new record, so that it wastes disc space and messing up the sequence of records. The requesce of records means for financeial sytem, the order of record is very ... basically the order of record is key for the performance. From hardware point of view our hard disk is composed of disk and reader. If record is ordered in the disk, it is not necessary to jump on the disk. It needs simply read in the disk. Also hard disk reads data based on block size, so that the record size is less than block size and block contains multiple records, one read can load multple record but if each recorrds are located in the multiple block, if the record are spreading in multiple blocks, the reader jumps on the disk and load block with unnecessary memory. For example, the recorrd size is 1k and block size is 4k, then each block has only one record to be load, then that waste 4 times. If it uses RAID 5, that waste will increase related to the number of disk theoretically.
The advantage for C++ are;
For memory issue for modern interpreter language. sometimes I found a code which uses constructtor to switch on and destructor to switch off but this approach is only effective C/C++ language. Other interupter language will cause issue this approach because some interrupter language will not gurantee the execution of destructor. Instead use of destructor, most interpreter language supports try-catch-finally functtionality to execute codes developer intendedly in the end of source code in finally block.
Quote Time Out
It has Quote Time Out event. The concern is that we have three times, trader PC, client PC, and server. The message will flow from trader quote to client through server. If time is differnt for three, it will makes confuse. The solusion is that trader calculate quote on the server based on latest spot price so that server time is the base time to be calculated expiry time for the quote. Every calculate quote put the current time and calculates the quote expiry time.
Smart Pointer Policy
This application mainly uses unique_ptr<T> and shared_ptr<T>.
The auto_ptr<T> is not used in this application because it is deplicated after C++11 which introduces unique_ptr<T>, shared_ptr<T>, and weak_ptr<T>.
The unique_ptr<T> is the firstest smart pointer in those three pointers and it is not so much different comparing pointer.
The unique_ptr will be maily used.
The concern is that;
Only one unique_ptr can point to the object, two unique_ptr cannot have the ownership to the object.
the unique_ptr cannnot share the ownership of the object in the application.
the unique_ptr is mainly used in the case of holding a pointer as a local variable or guaranteed to use only in a single place.
Smart pointers are a wrapper class for a C++ pointer to manage the lifetime of the object being pointed to.
It needs still new but it is not necessary to call delete.
Also even these are a wrapper class for a pointer but we can use operators '*' and '->' to the object pointed to.
Smart pointers are working like a pointer pointing to the object.
It is not necessary to call 'delete'.
For C++ resource management,
the smart pointer is a class to hold a pointer and delete the object the pointer refers to in the destructor.
the smart pointer should be in the stack memory so that the destructor has to be called whenever it is out of scope.
we can use finally statement to place a process to release resources safely but from RAII (Resource Acquisition Is Initialization) point of view, using constructor and destructor for managing resources using stack memory is more safer than using finally to release resources.
One of concern for using finally is that a variable is decleared out of try and finally clauses, comparing RAII, RAII is simpler than using finally clause.
The object must be allocated and immediately passed to the constructor of a smart pointer constructor for the policy of RAII.
The unique_ptr is the first option to use a smart pointer and if it is not possible to use it like it needs to share in multiple places, then shared_ptr must be used.
the performance is the primary priority in this application.
Comparing unique_ptr and shared_ptr, the unique_ptr is better performance than shared_ptr.
The smart pointer reduces risk to the dynamic allocated memory leak in the heap memory.
The unique_ptr performance is higher than shared_ptr because;
- only one smart pointer can own ownership of the pointer refering to the object.
- ownership cannot copy to other smart pointer, it needs to use std::move to move ownership from one smart pointer to another.
The shared_ptr is slower than unique_ptr but usability is higher than shared_ptr.
- It can copy from one shared_ptr to another with operator, "=".
- It has counter and if all the variables are no longer used, then it will be released.
Both do not need to call "delete", so that if a smart pointer is used appropriately with a dynamic memory allocation in the heap memory, it is not necessary to call "delete" but the smart pointer uses RAII, so that it needs to consider
The ownership means the right to access an object allocated in the heap memory and the obligation to delete it.
C++14 provides make_unique function to create an unique_ptr.
auto up = std::make_unique<int>(12);
auto m = [up1 = std::move(up)]()mutable{ // in this case, () and mutable are mundatory
auto up2 = std::move(up1);
};
To delete allocated memory, it must be released with destructor or reset method.
The operator bool() can test whether it has ownership or not for a pointer.
The release method never delete the object a pointer referes to.
It can use not only memory management but also for resource management using deleter.
To declare deleter in the second parameter in the template, it will be called in the destructor.
struct my_deleter {
void operator()(int* ptr){
free_ptr(ptr);
}
};
int main(){
unique_ptr
return 0;
}
shared_ptr can hold ownership in multiple shared pointers.
shared_ptr has couunter to count of pointers which obtain ownership.
Calling destructor and release method decrement the counter.
It release the object after all the ownership has been released.
It supports copy and move.
It is slower than unique_ptr because of counter.
It can use array but needs to specify deleter.
A shared_ptr needs memory allocation for managing counter. The make_shared function can create shared_ptr effectively.
RAII is the technic for resource management when object in the stack is out of the scope, it automatically executes the destructor. It is not necessary to use finally like Java or Phython.
std::thread vs posix threads
This application is targeted to only Linux/gcc, so that this application uses only std::thread. If it needs to support multiple platform, it should use the Posix Threads. If it needs to support multiple platform without using the Posix thread, try to use boost::thread. The interface is very similer to the std::thread. Also it needs -pthread option to g++ or clang++ with C++11 or newer. Without this option, it becomes runtime error, not compile error.
React.js test method
For unit test, there are mocha, Jasmine, Jest, AVA, etc. The Jest is bundled with create-rest-app.
+Call-Put = +Forward Long Call and Short Put position is the same position as long forward.