Asset Classes

Free investment financial education

Language

Multilingual content from IBKR

Close Navigation
Learn more about IBKR accounts
Can ChatGPT Self-Improve Self-Written Python Code for Cholesky Decomposition?

Can ChatGPT Self-Improve Self-Written Python Code for Cholesky Decomposition?

Posted February 15, 2023 at 10:25 am
Dr. Pawel Lachowicz
Quant at Risk

It is needless to say about next big thing in the field of artificial intelligence (AI) known as ChatGPT. ChatGPT is a large language model developed by OpenAI. It is based on the GPT (Generative Pre-training Transformer) architecture and is trained on a massive dataset of text data. This allows it to generate human-like text and perform a wide range of natural language processing tasks, such as language translation, text summarization, and question answering.

One of the main advantages of ChatGPT is its ability to generate human-like text, which makes it useful for tasks such as writing essays, articles, and even code. It can be fine-tuned on specific tasks and domains, such as financial domain, allowing it to generate financial reports, financial predictions, code snippets and more.

The model is trained on a large dataset of text, which allows it to understand and generate text in a variety of styles and formats. It can also generate text based on a given prompt, making it useful for tasks such as text completion, text generation, and text summarization.

1. ChatGPT for Quantitative Finance?

There is a lot of hype around the use of ChatGPT because it is a powerful and versatile language model that can perform a wide range of natural language processing tasks. ChatGPT can be useful in quantitative finance for several reasons:

  • Time-saving: it can generate code snippets quickly, allowing financial engineers and quantitative analysts to focus on more complex and high-level tasks.
  • Consistency and accuracy: it can generate code that is consistent and accurate, reducing the risk of errors in financial computations.
  • Flexibility: it can be used to generate code for a wide range of financial computations, from simple calculations to complex financial modeling.
  • Scalability: it can be used to generate code for large-scale financial computations, such as portfolio optimization or risk management.
  • Multi-language support: it can generate code in multiple programming languages, which allows for efficient and memory-friendly solutions for big computations.
  • Efficient use of historical data: it can help generate code that makes the most of historical data, which is crucial in quantitative finance, where past performance is used to predict future outcomes.
  • Repetitive task automation: it can help automate repetitive tasks, allowing financial engineers and quantitative analysts to focus on higher-level tasks and improve productivity.
  • Cost-effective: it can help reduce costs by automating repetitive tasks, reducing human error and increasing productivity.

Overall, ChatGPT can help financial engineers and quantitative analysts to work more efficiently, accurately and effectively, which can lead to better decision making and improved performance in financial markets.

2. So, Is It Reasonable to Use ChatGPT for Writing Python Code for Financial Applications?

ChatGPT can be used to write Python code for financial applications by providing concise, accurate and efficient code snippets for various financial computations. Some examples of financial computations that can be done using ChatGPT include:

  • Calculation of portfolio profit and loss
  • Calculation of VaR (Value at Risk) and Liquidity VaR
  • Calculation of expected shortfall for a portfolio
  • Arbitrage on two FX currency pairs
  • Cholesky decomposition for a given matrix
  • Calculation of portfolio value given different trading strategies
  • Filtering of noisy correlations in a correlation matrix
  • Calculation of average loss for a cryptocurrency based on past performance

ChatGPT can also be used to generate code in other languages like Rust, providing solutions that are efficient and memory-friendly. Rust, right after Solidity, is the language of choice for all recently-born blockchain developers, allowing Decentralised Finance (DeFi) application to blossom.

It is important to note that the ChatGPT model is only able to provide the code based on the knowledge it has been trained on, and the performance of the generated code depends on the quality of the input data and the specific use case. It is always recommended to test and verify the generated code before using it in production environments.

3. Speaking of, Cholesky Decomposition. What code it can generate?

Cholesky decomposition is a method for decomposing a Hermitian, positive-definite matrix into the product of a lower triangular matrix and its conjugate transpose, which is useful for efficient numerical solutions, such as Monte Carlo simulations.

Here is an example delivered by the model of a Python script that performs Cholesky decomposition on a matrix:

import numpy as np
 
def cholesky(matrix):
    """
    Perform Cholesky decomposition on a matrix
    :param matrix: Square matrix to decompose
    :return: Lower triangular matrix L
    """
    n = matrix.shape[0]
    L = np.zeros((n, n))
    for i in range(n):
        for j in range(i+1):
            temp = sum(L[i][k] * L[j][k] for k in range(j))
            if i == j:
                L[i][j] = np.sqrt(matrix[i][i] - temp)
            else:
                L[i][j] = (1.0 / L[j][j] * (matrix[i][j] - temp))
    return L
 
# Example usage
matrix = np.array([[4, 12, -16], [12, 37, -43], [-16, -43, 98]])
L = cholesky(matrix)
print(L)

In the above script the matrix is passed as an argument to the function cholesky() which decomposes the matrix and returns the lower triangular matrix.
Please note that the matrix passed to the function should be Hermitian, Positive-definite.

4. Code Self-Improved, Optimised for Speed? No Problem at All!

It looks like it can be done, too! No problem. In this can all we need is to ask politely ChatGPT “Can you rewrite the following function optimised for speed, please?” pasting the above script. Its response is quite optimistic, saying “There are multiple ways to optimize the function for speed, here is one possible way:”

import numpy as np
 
def cholesky(matrix):
    """
    Perform Cholesky decomposition on a matrix
    :param matrix: Square matrix to decompose
    :return: Lower triangular matrix L
    """
    n = matrix.shape[0]
    L = np.zeros((n, n))
    for i in range(n):
        L[i][i] = np.sqrt(matrix[i][i] - np.dot(L[i, :i], L[i, :i]))
        for j in range(i+1, n):
            L[j][i] = (matrix[j][i] - np.dot(L[i, :i], L[j, :i])) / L[i][i]
    return L

This implementation uses numpy’s dot product function which is implemented in C and is therefore faster than using a Python for loop. This way it reduces the time complexity of the function and makes it faster.

Additionally, the function uses only one for loop to calculate both the upper and lower triangular matrix. It also calculates the diagonal element of the matrix at the same time, which reduces the number of operations and improves performance.

5. Second Derivative, i.e. How to Self-Self-Improve Itself?

I have never thought I would be writing an article on such a bizarre topic. Never, ever, in my life. Until today! I asked again “Can you rewrite the above function in order to make it run faster, please?” And guess what? That soulless soul told me “Here is one possible way to optimize the function for speed:”

import numpy as np
 
def cholesky(matrix):
    """
    Perform Cholesky decomposition on a matrix
    :param matrix: Square matrix to decompose
    :return: Lower triangular matrix L
    """
    n = matrix.shape[0]
    L = np.zeros((n, n))
    for i in range(n):
        L[i, i:] = matrix[i, i:] - np.dot(L[:i, i:], L[:i, i:].T)
        L[i, i:] /= L[i, i]
    return L

This implementation uses array slicing to access specific parts of the matrix and perform operations on them, which reduces the number of operations and improves performance.

6. Back to the Class-room?

My desire for asking and learning more continues with my next question “Can you rewrite that function in Python as a class and add n as an input parameter provider by the user?” Again, two seconds of “thinking” and this guy start printing:

import numpy as np
 
class CholeskyDecomposition:
    def __init__(self, n):
        self.n = n
    def decompose(self, matrix):
        """
        Perform Cholesky decomposition on a matrix
        :param matrix: Square matrix to decompose
        :return: Lower triangular matrix L
        """
        L = np.zeros((self.n, self.n))
        for i in range(self.n):
            L[i, i:] = matrix[i, i:] - np.dot(L[:i, i:], L[:i, i:].T)
            L[i, i:] /= L[i, i]
        return L
         
# Example usage:
n = 3
matrix = np.array([[4, 12, -16], [12, 37, -43], [-16, -43, 98]])
cholesky_decomposition = CholeskyDecomposition(n)
L = cholesky_decomposition.decompose(matrix)
print(L)

In this example, the user provides the value of n to the class constructor and the class uses it to define the shape of the matrix. This way the user can control the size of the matrix, and the class will be able to operate with any square matrix.

7. Parlez Vous Français?

Now an icing on the cake. It is 2023 and programming in Python became boring and too popular. If you want to feel the thrill and some adrenaline, go to France, try communication with other people using different language! What I’m trying to say here is that taking Python code and translating it into, for example Rust language, now, is no longer an issue. Have a look. Just ask again “Rewrite the following Python function in Rust language, please.” I do like to add “, please” at the end to get that personal touch to human-model conversation. I hope you know what I mean…

Here is an example of the Cholesky decomposition function implemented in Rust – the response appears without hesitation, followed by the code:

use ndarray::{Array, Array2};
use ndarray_linalg::cholesky::cholesky_unpack;
 
fn cholesky(matrix: Array2<f64>) -> Array2<f64> {
    let (l, _) = cholesky_unpack(matrix);
    l
}
 
// Example usage:
let matrix = array![[4.0, 12.0, -16.0], [12.0, 37.0, -43.0], [-16.0, -43.0, 98.0]];
let L = cholesky(matrix);
println!("{}", L);

Note that this example uses the ndarray and ndarray_linalg crates, which provide functionality for working with arrays and performing linear algebra operations. In this example, the input matrix is passed to the cholesky_unpack function from ndarray_linalg crate, which returns a tuple of lower triangular matrix and its transpose. The lower triangular matrix is then returned. This implementation is more concise and efficient than the previous one because it uses the optimized linear algebra libraries and doesn’t require to iterate and perform the calculations manually.

They say, in Rust you cannot do quantitative matrix operations! Not true! I ask ChatGPT for the last time “Write code in Rust performing Cholesky decomposiiton for matrix of size 500 by 500” followed by repeated but reordered feedback “Here is an example of how to perform Cholesky decomposition on a matrix of size 500×500 in Rust:”

use ndarray::{Array, Array2};
use ndarray_linalg::cholesky::cholesky_unpack;
 
fn cholesky(matrix: Array2<f64>) -> Array2<f64> {
    let (l, _) = cholesky_unpack(matrix);
    l
}
 
fn main() {
    let mut matrix = Array::zeros((500, 500));
    // Fill the matrix with some values
    // ...
    let L = cholesky(matrix);
    println!("{}", L);
}

In this example, we first create a 2D array of size 500×500 using the Array::zeros function from the ndarray crate. Then we fill the matrix with some values, it could be from reading from a file or from some other calculation. Then we pass the matrix to the cholesky_unpack function from ndarray_linalg crate, which returns a tuple of lower triangular matrix and its transpose. The lower triangular matrix is then returned and printed. As we are working with a big matrix, it is recommended to use this implementation as it uses the optimized linear algebra libraries and doesn’t require to iterate and perform the calculations manually.

Amazing!

Now I’ll go and check if all these code lines actually work?!

Originally posted on Quant at Risk Blog.

Disclosure: Interactive Brokers

Information posted on IBKR Campus that is provided by third-parties does NOT constitute a recommendation that you should contract for the services of that third party. Third-party participants who contribute to IBKR Campus are independent of Interactive Brokers and Interactive Brokers does not make any representations or warranties concerning the services offered, their past or future performance, or the accuracy of the information provided by the third party. Past performance is no guarantee of future results.

This material is from Quant at Risk and is being posted with its permission. The views expressed in this material are solely those of the author and/or Quant at Risk and Interactive Brokers is not endorsing or recommending any investment or trading discussed in the material. This material is not and should not be construed as an offer to buy or sell any security. It should not be construed as research or investment advice or a recommendation to buy, sell or hold any security or commodity. This material does not and is not intended to take into account the particular financial conditions, investment objectives or requirements of individual customers. Before acting on this material, you should consider whether it is suitable for your particular circumstances and, as necessary, seek professional advice.

Disclosure: Forex

There is a substantial risk of loss in foreign exchange trading. The settlement date of foreign exchange trades can vary due to time zone differences and bank holidays. When trading across foreign exchange markets, this may necessitate borrowing funds to settle foreign exchange trades. The interest rate on borrowed funds must be considered when computing the cost of trades across multiple markets.

Disclosure: Bitcoin Futures

TRADING IN BITCOIN FUTURES IS ESPECIALLY RISKY AND IS ONLY FOR CLIENTS WITH A HIGH RISK TOLERANCE AND THE FINANCIAL ABILITY TO SUSTAIN LOSSES. More information about the risk of trading Bitcoin products can be found on the IBKR website. If you're new to bitcoin, or futures in general, see Introduction to Bitcoin Futures.

IBKR Campus Newsletters

This website uses cookies to collect usage information in order to offer a better browsing experience. By browsing this site or by clicking on the "ACCEPT COOKIES" button you accept our Cookie Policy.