After my preparatory classes in Marseille and Douai (with a specialization in mathematics, philosophy and geopolitics), I enrolled in the Grande Ecole program at EDHEC Business School, where I got a MSc Finance and a Master’s in Management.
In the mean time, I finished a double license in Business Law and Management at the Catholic University of Lille.
My time at EDHEC Business School taught me a lot about Financial Markets, Financial Econometrics, VBA and Portfolio Construction Theory. I was able to use that knowledge and skills during a six months internship at Société Générale as a sales assistant on a structured products desk.
Besides that, I enjoy coding on my free time and build finance related algorithms as side projects. I have developed and used statistical arbitrage algorithms to profit from oversold or overbought stocks. Below are presented some side projects I’ve worked on. Oh and I like cooking too!
As of now, I’m working in Paris as a Financial Markets Consultant.
1. Rationale for the Statistical Arbitrage
2. Finding suitable pairs of stocks
3. When to open and close positions?
The goal of a StatArb Algorithm is to profit from two stocks that are usually very close in value when they diverge unusually from one another.
When two stocks are very related in price and when they diverge on the short term, they are sometimes statistically prone to Return To The Mean, that is to say, they are probabilistically going to converge in price in the future.
We can prove that this is very much probable for some pairs of stocks by verifying that their stock returns are statistically cointegrated.
We can check for candidates by looking at stocks with particularly high correlation in stock returns, and then checking if they verify all the statistical prerequisites for the StatArb strategy to perform.
Once this is done, we need to create a signal to check for opportunities in stocks diverging too much on the short term.
This way, a trader can class opportunities every day and enter multiple Long/Short trades for different pairs of stocks.
The Long/Short strategy can return very decent returns while providing virtually very low risk, with a beta of approximately 0 compared with the market. This is thus considered a market neutral strategy.
def rank(pairs):
i = 0
ranking = pd.DataFrame(columns=["Pair", "Beta", "Kappa", "Mean", "Sigma_eq", "Score"])
for pair in pairs:
pair = eval(pair)
reg = trailing_regression(pair)
if (252/reg[1]) < 20:
ranking.loc[i] = [pair, reg[0], reg[1], reg[2], reg[3], 0]
i += 1
#adjust the mean and determine the score
m_hat = ranking["Mean"].mean()
for j in range(len(ranking)):
m_adj = (-ranking.loc[j, "Mean"] + m_hat).item()
sigma_eq = (ranking.loc[j, "Sigma_eq"]).item()
score = (m_adj/sigma_eq)
ranking.at[j, "Score"] = score
return ranking
First, we need to find stocks that are highly correlated, this is the first step of finding potential candidates for a statistical arbitrage
Second, once we have found stocks that are really correlated, we need to verify whether they share a long-term trend.
In statistical terms, we need to verify that these stocks have a weak stationarity when compared. In other words, we write a linear combination of return of pairs, such that they are cointegrated.
- We need to compute regressions of one stock price over the other
- We need to verify that the intercept is not different from 0
- We need to test the stationarity of the error terms in order to assess or reject the presence of a spurious regression
- We will class the pairs in terms of higher correlations and higher R2 (test these pairs first)
- We need to write a linear combination of returns for pairs, such that they are cointegrated
def trailing_regression(pair):
r_1 = data[pair[0]]["Close"].pct_change().dropna()
r_2 = data[pair[1]]["Close"].pct_change().dropna()
df = pd.merge(left=r_1, left_on='Date', right=r_2, right_on='Date').dropna()
influence = sm.OLS(df["Close_x"], df["Close_y"]).fit().getinfluence()
standardized_residuals = influence.resid_studentized_internal
X = [sum(standardized_residuals[-i:]) for i in range(len(standardized_residuals))]
ar_mod = AR(X).fit(1)
a = ar_mod.params[0]
b = ar_mod.params[1]
var = np.var(ar_mod.resid)
kappa = -math.log(b)*252
m = a/(1-b)
sigma = np.sqrt((var*2*kappa)/(1-b**2))
sigma_eq = np.sqrt(var/(1-b**2))
return [model.params[0], kappa, m, sigma_eq]
We model the pairs relation with an OU process so that we can measure the reversion to the mean average time and get statistically defined thresholds for when to enter trades or not. We want to make sure that kappa > 252/20, which means that the average reversion time is no more than 1 month. We calculate a score and we decide to buy and sell at certain thresholds.
For example, when the score goes above 1.25, we long the second stock and short the first one. Using the pair's bêta, we can find the adequate quantities of stocks to long and short such that the positions cancel each other in comparison with the market, hence the market neutral nature of this strategy.
Whenever the score goes below 0.5, we close that position.
Conversely, when the score goes below -1.25, we long the first stock and short the seconde one. We close that position if the score goes above -0.5.
1. Rationale for the Constant Portfolio Protection Insurance
2. Implementing the CPPI Strategy
3. Finding good risky assets, safe assets, and multipliers
During my final year at EDHEC Business School, I had the chance to attend an elective taught by Pr. Lionel Martellini and Pr. Vijay Vaidyanathan on Portfolio Construction with Python.
This course taught basic skills for comparing stock returns, calculating volatility, sharpe ratios, finding optimal theoretical weights for a minimum volatility portfolio, and so on.
Another part of the course was aimed at designing a CPPI: Constant Portfolio Protection Insurance, in order to generate a portfolio that would never go as low as a certain threshold, for example 80% of the previous maximum net asset value recorded in history.
The goal of the CPPI strategy is to decrease the investment in risky assets when the net asset value drops too low. At the contrary, when the net asset value is well below the previous maximum net asset value, 100% of the portfolio is invested in high risk/high return assets.
We can develop a Monte Carlo simulation to try and perfect our CPPI strategy by finding the best fitting weights for risky assets, safe assets, and the multiplier.
The whole point of the CPPI Strategy is protecting a good portion of the invested capital in the worst cases (as the COVID-19 outbreak related crisis) while still offering most of the upside when the markets are bullish.
Thanks to a Monte Carlo simulation, we can find which protection threshold and what investment leverage minimizes the financial losses during market crashes. Of course, the CPPI strategy is not 100% bullet proof and it can sometimes lead to losses below the initial threshold.
• The best performing portfolio has a low multiple (4), low floor (80%) and low rebalancing frequency (monthly). However, it is also the most negatively skewed strategy, and the biggest VaR and CVaR.
• The rebalancing frequency greatly reduces the VaR and CVaR. Portfolios with Weekly rebalancing have ~2.5% VaR and ~3.5% CVaR while portfolios with monthly rebalancing have ~5% VaR and ~7.2% CVaR.
• Returns are tightly distributed, between 7.6% and 9.2%.
• Volatility is even more tight: it ranges between 11.5% and 12.4%.
Conclusion for the positive economic scenario:
• A rational investor who wants to protect capital should rebalance often (given negligeable rebalancement costs)
• A medium multiple (4) tends to yield better Sharpe Ratios.
Once all the backtesting work has been done, we can come up with a reasonable model with optimal parameters. Here is my personal try at making a CPPI strategy using available equity and bond ETFs for the risky/safe assets weights. I also did some backtests with my ideal weights, multipliers and rebalancements, with a homemade backtesting function using Python. This yielded good results, as the CPPI strategy allowed for the volatility to go way down as compared with the benchmark.
risky_w = [0.5,0.1,0.3,0.1,0,0,0,0]
safe_w = [0,0,0,0,0.1,0.6,0.1,0.1]
cppi_controls = widgets.interactive(
cppi_rebal,
returns=fixed(rets),
risky_w=fixed(risky_w),
safe_w=fixed(safe_w),
m=widgets.FloatSlider(min=0, max=5, step=0.25, value=5),
start=(1000, 100000, 1000),
floor=(0, 1, .05),
drawdown=widgets.FloatSlider(min=0, max=1, step=0.01, value=0.2),
nb_rebalancements_per_year=[("Annual", 1),
("Bi-Annual", 2),
("Quarterly", 4),
("Monthly", 12),
("Weekly", 52),
("Daily", 252)],
rebalancement_cost=widgets.FloatSlider(value= 0.0001, min=0, max=0.01, step=0.0001, readout_format='.3f'))
display(cppi_controls)
1. Rationale
2. Portfolio Composition
3. Historical Performance
I wanted to have some kind of public track record of my personal investments so that they could compound and amount to a public state of my financial performances. I do have multiple accounts on online platforms as well as in the bank, but this part only focuses on my public online portfolio, consisting of a simple buy and hold strategy.
In this portfolio, I use tools that I have either learned to implement during classes or that I have developed on my free time. The goal is to come up with a simple portfolio, mainly based on well known ETFs, to show that portfolio construction can be kept simple and effective.
The portfolio composition is bound to change a lot, and the portfolio is rebalanced every month to fit the strategy. Historically, I have made ~2 trades per week for year 2020 on that portfolio.
The main components are USA equity ETFs (MTUM, SPLV, SPY and VTI), which are completed by a small portion of a gold ETF (GLD), Bitcoin, and two oil stocks (FP.PA and OXY).
The oil and gold/cryptocurrency components of the portfolio are there for hedging purposes because oil is known to behave differently than the rest of the market and because gold/crypto are considered to be safe havens in times of market crashes.
I chose to overinvest in MTUM because I think Momentum has been one of the hottest factors in the stock market in the recent years and is still today.
2020 was a particularly good year for the stock market, despite the COVID-19 pandemic bursting. This is mainly due to tech stocks continuing to surge as more and more people experienced lockdown all over the developed world.
Up until April, I had a somewhat conservative portfolio (based on SPLV – low volatility stocks as compared with the market), and decided to increase the volatility of my portfolio to get better potential returns.
You can follow my personal portfolio on eToro following this link. I chose this platforme so that people can copy my portfolio or read my investment strategies. During year 2020, multiple copiers have decided to let me make investment decisions for them. Mid December 2020, I had 6 copiers.