Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create PostPairsTrading.md #11

Open
wants to merge 69 commits into
base: 2-basic-study-of-pair-trading-using-linear-regression
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
36efa3b
Create PostPairsTrading.md
Kokechacho Apr 8, 2024
70bc399
Add files via upload
Kokechacho Apr 8, 2024
33eaf4c
Add files via upload
Kokechacho Apr 8, 2024
143b253
Add files via upload
Kokechacho Apr 8, 2024
410b768
Update PostPairsTrading.md
Kokechacho Apr 8, 2024
26301b1
Update PostPairsTrading.md
Kokechacho Apr 9, 2024
7ea8bd4
Add files via upload
Kokechacho Apr 9, 2024
74fdca3
Add files via upload
Kokechacho Apr 9, 2024
c3fdb67
Add files via upload
Kokechacho Apr 9, 2024
22b9ec8
Add files via upload
Kokechacho Apr 10, 2024
855277f
Update PostPairsTrading.md
Kokechacho Apr 10, 2024
49a0bd6
Add files via upload
Kokechacho Apr 15, 2024
339e18a
Update PostPairsTrading.md Iteration 1
Kokechacho Apr 15, 2024
a0b7604
Update PostPairsTrading.md Iteration 1
Kokechacho Apr 15, 2024
9d884cb
Update PostPairsTrading.md -> Iteration 2 Added code, extended explan…
Kokechacho Apr 16, 2024
2bea233
Added images folder
Kokechacho Apr 18, 2024
5c786d3
Uploaded new gifs and added them to the post
Kokechacho Apr 18, 2024
248adfd
Add files via upload
Kokechacho Apr 18, 2024
1fa999a
Delete resources/Prices gif.gif
Kokechacho Apr 18, 2024
569b53d
Add files via upload
Kokechacho Apr 18, 2024
55f3343
Update PostPairsTrading.md Added some review changes
Kokechacho Apr 30, 2024
e9184dc
Update PostPairsTrading.md
Kokechacho May 7, 2024
cdfad08
Add files via upload
Kokechacho May 7, 2024
97f266a
Update PostPairsTrading.md
Kokechacho May 7, 2024
6b81f23
Update PostPairsTrading.md
Kokechacho May 7, 2024
7fc14fd
Update PostPairsTrading.md
Kokechacho May 7, 2024
96bcbaa
Small changes based on my previous comments
nipsn May 8, 2024
579baa1
ADF test code refactored
chraberturas May 13, 2024
4b5a104
Merge branch '5-Post' of https://github.com/hablapps/pairstrading int…
chraberturas May 13, 2024
79fb6ee
added stocks data
chraberturas May 13, 2024
ab9050c
Fixed execution
nipsn May 14, 2024
d9efeb2
Adapted pykx to use q-like syntax
nipsn May 14, 2024
7b4651b
minor refactor
chraberturas May 14, 2024
4c7203c
Add heatmap & plotting mention
nipsn May 16, 2024
dc9a86b
refactor the post considering the latest changes in the code, as well…
chraberturas May 16, 2024
5e060f2
minor changes
nipsn May 16, 2024
4348232
Reformatted the file (check TODOs)
nipsn May 21, 2024
f7a2465
ADF chapter refactored
chraberturas May 22, 2024
2ddc2a2
minor corrections
nipsn May 22, 2024
e6c653f
refactored spreading spreads
chraberturas May 23, 2024
afbefc0
removed last TODO
chraberturas May 23, 2024
80fcc3b
minor spelling mistakes
nipsn May 23, 2024
83be685
added generic formula
chraberturas May 23, 2024
a19e3cc
addressed some of the comments
nipsn May 24, 2024
a57a3ac
added p-value explanation and addresed rest of comments
chraberturas May 27, 2024
e5710aa
refactor (WIP) and solve problems in real time script
chraberturas May 28, 2024
0f39e45
uploaded images
chraberturas May 28, 2024
1ab6f8e
added images and their explanations, and also made a major refactor o…
chraberturas May 28, 2024
786bb8e
Minor adjustments
nipsn May 28, 2024
03c6880
fix data
chraberturas May 29, 2024
06224b5
Merge branch '5-Post' of https://github.com/hablapps/pairstrading int…
chraberturas May 29, 2024
4605d9e
refactored real time section and addresed the rest of comments
chraberturas May 29, 2024
135c393
refactored real time section and addresed the rest of comments
chraberturas May 29, 2024
41733c2
Merge branch '5-Post' of https://github.com/hablapps/pairstrading int…
chraberturas May 29, 2024
c566387
Minor typos and corrections
nipsn May 29, 2024
ff1dc17
refactored conclusion and future work section
chraberturas May 30, 2024
dc68da1
Merge branch '5-Post' of https://github.com/hablapps/pairstrading int…
chraberturas May 30, 2024
f1b0bf4
refactored based on comments
nipsn May 30, 2024
d815f26
addressed comments
chraberturas May 30, 2024
9a04521
minor tweaks
nipsn May 31, 2024
76561a8
minor typos
nipsn May 31, 2024
05aa9e1
added diagram and brief introduction
nipsn May 31, 2024
9024579
refactor (added kdb tick context)
chraberturas May 31, 2024
b0192f8
minor changes
nipsn Jun 3, 2024
d3a5fd3
more minor changes
nipsn Jun 3, 2024
0ac45dc
minor fixes
chraberturas Jun 4, 2024
636eff5
further revisions
nipsn Jun 4, 2024
fc66279
refactored real time part and added a minor introduction to tick arch…
chraberturas Jun 5, 2024
e47d499
Minor tweaks
nipsn Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added ADFgif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added CointAlGif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
260 changes: 260 additions & 0 deletions PostPairsTrading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
# A Match Made in Trading: Step by Step Pairs Trading Guide
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Q/kdb+ stands out as **a powerful tool in finance**, renowned for its ability to handle vast volumes of real-time data amidst the relentless dynamics of the market. In this article, we embark on an insightful exploration of pair trading and its implementation in Q, offering a comprehensive guide to one of the most popular strategies in the trading world.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Our objective is to **provide a deep understanding of the intricacies of pair trading**, bridging the gap between theory and practice. Through a blend of theoretical insights and practical examples, we aim to equip you with the knowledge and skills necessary to navigate every aspect of this financial modeling strategy.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

We'll proceed methodically, ensuring each question leads to a comprehensive answer. To start, we'll contextualize our current situation by addressing key questions such as **"What do we know about the market and how can we benefit from it?"**. This will lay the foundation for constructing a real-time simulated environment on Pairs Trading that will exemplify everything we have explained thus far.

Whether taking a technical or quantitative approach, these insights will provide valuable foundations for constructing this algorithm effectively.

## In the untamed realm of the market.

The market has often been described as a **stochastic** (a term which essentially means random) **process** where prices fluctuate irregularly. However, amidst this apparent randomness, we observe that **certain assets move in tandem** due to their inherent relationships.

For instance, it's logical to expect that if the prices of petrol rise, the prices of cars should also rise. This is because auto companies rely on petrol for their operations, indicating an interconnectedness between the two. Over the long run, they tend to follow similar trends, **reflecting their underlying relationship**.

Is this described mathematically? **Yes**:

The concept we're referring to is **cointegration** (although there are other methods, we'll focus on this one).

> 💡 Which should not be confused with correlation; cointegration is a statistical property of two time series, indicating a long-term relationship between them despite short-term fluctuations. Cointegrated series move together over time, sharing a common stochastic drift. On the other hand, correlation measures the strength and direction of the linear relationship between two variables at a specific point in time. While correlation captures the degree of association between variables, cointegration reflects a deeper, underlying relationship that persists over time.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Hence, we're interested in **cointegrated assets**, which are assets that exhibit the following characteristics:

1. They have a similar trend, meaning the difference between both assets maintains a constant mean, and this difference fluctuates around that same mean.

2. This inherent relationship persists in the long run, meaning that our series is not dependent on time.
Copy link
Member

@neutropolis neutropolis Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should add a new section, which supplies a very brief intro to the components of the classical Tick Architecture. I would end up clarifying the next section. First, we'll identify cointegrated pairs. Then, we'll produce the Pairs Trading model to calculate spreads. Finally, we'll exploit such model from a real-time component and will visualise its outcomes.


## A pair in the hand is worth two in the bush.

### ADF testing
nipsn marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, this section becomes "Identifying cointegrated indexes" or something like that...


Imagine **we selected 13 world indexes** and aimed to assess whether they are **cointegrated or not**. In this scenario, a crucial tool at our disposal is the Augmented Dickey-Fuller (ADF) test.

> 💡 Please note that for simplicity in this code, we will be using pykx. This is necessary as we need to import our ADF test function and plot a heatmap of our results.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

> `system "l pykx.q"`
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Next, we import the statsmodels.tsa.stattools library and define a custom cointegration function that returns a dictionary with the ADF test results given 2 assets. **We then apply our cointegration function to the Cartesian product of every pair of assets** to get a matrix with every p-value.
chraberturas marked this conversation as resolved.
Show resolved Hide resolved
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

![cointegration](https://github.com/hablapps/pairstrading/blob/5-Post/CointAlGif.gif?raw=true)

---

```q
// Recieves 2 symbols and returns a dictionary
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

fCoint {[assetX;assetY;]
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
... }

crossedList: symList cross symList
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that crossedList and symList also need to be polished, we could be more 'q' idiomatic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if I understand what you mean by this. Should I just join this 2 lines together? and leave it with something like:

crossedList: x cross x: exec distinct sym from superTab


matrix: fCoint .' crossedList;
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok to keep pairs with repeated assets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, cointegration is 2 directional, meaning that cointegration is different between A-B and B-A, so depends on the direction you are taking you will focus on one set of pairs or the opposite. In order to keep it generic I think this is ok.

```

---

Now, with our matrix in hand, we can plot it and **visually identify** which asset is more favorable. Given our following assets:
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved


| SP500 | NASDAQ100 | BFX | FCHI | GDAXI | HSI | KS11 | MXX | N100 | N225 | NYA | RUT | STOXX |
|:---------:|:---------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| USA | USA | Belgium | France | Germany | Hong Kong|S.Korea | Mexico | Europe | Japan | USA | USA | Europe |

![ADF heatmap](https://github.com/hablapps/pairstrading/blob/5-Post/ADFgif.gif?raw=true)

As we can observe, there are several cointegrated indices, but our attention will be drawn towards the **NASDAQ100 and SP500** synergy. Both of these indices belong to the American market and share numerous characteristics. They encompass American companies traded within the same scenario, what makes them a perfect fit for our case.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

## Cointegration, then what?

Let's recap our progress:

1. We've acknowledged the randomness of the market, yet discovered that certain assets **exhibit similar movements**.

2. By employing the **cointegration method and the ADF test**, we pinpointed a promising pair of assets for our analysis: NASDAQ100 and SP500.

3. These two assets exhibit similar movements and **tend to gravitate around a shared mean**.
chraberturas marked this conversation as resolved.
Show resolved Hide resolved

Now we're faced with a crucial question: **"What do I do with these assets?"**
chraberturas marked this conversation as resolved.
Show resolved Hide resolved

As mentioned earlier, the market is inherently random and doesn't always behave predictably. While NASDAQ100 and SP500 often follow similar trends, their individual values **can sometimes diverge significantly**. For instance, NASDAQ100 may rise while SP500 falls, or vice versa.

However, this presents **an opportunity for profit** because we know that these assets tend to revert to their shared mean over time. If one asset is **overpriced** and likely to decrease, we may consider **selling it** (going short). Conversely, if an asset is **underpriced** and expected to increase, we may consider **buying it** (going long). And that is what we call Pairs Trading.

> 💡 This strategy possesses intriguing financial characteristics: our **profitability remains unaffected by the broader market trends**, as our focus lies solely on the disparity between the two assets. It's about relative movements rather than absolute ones; we're indifferent to whether prices are rising or falling. This quality defines it as a **neutral market strategy**.

## Spreading spreads

Indeed, just subtracting the prices of two assets, as in: $priceY−priceX$ may not provide a clear understanding of their relationship. Let's illustrate this with an example:
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Consider the following series:

---

```q
priceX: 5 10 7 4 8

priceY: 23 30 25 30 35

spreads: priceY - priceX // = 18 20 18 26 27
chraberturas marked this conversation as resolved.
Show resolved Hide resolved
```

> 💡 As you can see and verify through Q/kdb+ array properties, spreads can be calculated by simply computing the difference between two vectors without the need for special functions or loops.

---

〽 **These spread values don't offer much insight** into the relationship between the two assets. Are both assets increasing? Are they moving in opposite directions? It's unclear from these numbers alone.

Let's consider **using logarithms**, as they possess favorable properties for our pricing model. They inherently prevent negative values and tend to approach zero:
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

---

```q
log priceX = 1.609438 2.302585 1.94591 1.386294 2.079442

log priceY = 3.135494 3.401197 3.218876 3.401197 3.555348

spreads: log priceY - log priceX // = 1.526056 1.098612 1.272966 2.014903 1.475907
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
```

---

We're making progress, as we observe **numbers now fluctuating within much smaller ranges**. However, we're still missing a clear understanding of the underlying relationship. While we've normalized the data using logarithms, we now need to align their discrepancies to a single asset.

Since both assets are related, **we can leverage linear regression** to our advantage. This enables us to simplify our spreads effectively. So, we'll conduct a basic linear regression analysis using historical data to discern the disparity between them:

---

$spread = log(priceY) - (beta * log(priceX)+alpha)$

```q
historical_data_priceX: 7 10 6 5 8

historical_data_priceY: 23 25 16 20 15

beta: 0.2679227

alpha: 2.444817
```
chraberturas marked this conversation as resolved.
Show resolved Hide resolved

---

We've already calculated the alpha and beta using the logarithmic values of our historical data (since we don't have prior knowledge of the real-time price values for priceX and priceY). Now, all that remains is to apply the previous formula to derive our spreads:

---

$spreads$ = -0.1493929 0.0451223 -0.08835117 0.0451223 0.1579725
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

---

And this precisely meets our objective—a **comprehensive method for representing relative changes between both assets**. As we can deduce, our mean is now 0 because our assets are normalized, cointegrated and on the same scale. Therefore, ideally, the differential between their prices should be 0. Consequently, when our spread is below 0, we infer that asset X is overpriced, whereas if it's above 0, then asset Y is overpriced.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

![Spreads](https://github.com/hablapps/pairstrading/blob/5-Post/Spreads.gif?raw=true)


## Two steps forward, one step back.

Before proceeding to plot the NASDAQ100-SP500 spreads, we need to first plan our algorithm. In this post, we intend to create **a real-time scenario** for Pairs trading, so careful planning is essential for our sake.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Decomposing our steps, let's start from the very beginning:

1. Data management part

1.1. Read data

1.2. Filter data

2. Outside the loop
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

2.1. Linear regression

2.2. Initialize values

3. Inside the loop

3.1. Calculate spreads

3.2. Write on buffers


As previously mentioned, historical data is crucial for generating accurate spreads. We need to calculate each spread in real-time **using precomputed alpha and beta values** derived from both prices. Therefore, once we have obtained our historical values, we can proceed with calculating our linear regression.

---

```q
// Fix data and take log(prices) -> Simulated data
priceX: 0!1_(update delta:0f^deltas dateTime from distinct select distinct dateTime, log bid, log ask from (update dateTime:"P"$@[;19;:;"."] each dateTime from tab1) where not null bid);
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
priceY: 0!1_(update delta:0f^deltas dateTime from distinct select distinct dateTime, log bid, log ask from (update dateTime:"P"$@[;19;:;"."] each dateTime from tab2) where not null bid);
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

// Read historical data
historial_tab2: 1_ flip `open`high`low`close`adjClose`vol!("FFFFFF";",") 0: `:/data/stocks/NASDAQ100_hist.csv;
historial_tab1: 1_ flip `open`high`low`close`adjClose`vol!("FFFFFF";",") 0: `:data/stocks/SP500_hist.csv;
chraberturas marked this conversation as resolved.
Show resolved Hide resolved
```

---

## Linear regression

Now, armed with logarithms, we can replicate the process from our previous example and calculate both alpha and beta values. To do this, we'll start by taking the historical data for NASDAQ100 and SP500 and applying our linear regression function to derive the desired values.

---

```q
// Calculate alpha and beta from historical values
beta_lr: betaF[px:-100#log historial_tab1`close;py:-100#log historial_tab2`close]; // we only take most recent 100 values
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
alpha_lr: alphaF[px;py];
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I miss the pub method from the RPT component itself, where you accumulate on the prices table. Which component is responsible for cleaning the published spreads?


---

Now we just calculate our spreads as we did before like:

---

```q
spread: priceY[.streamPair.i][`bid] - ((priceX[.streamPair.i][`bid] * beta_lr)+alpha_lr);
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
```

---

> 💡 You may notice that we retrieve bid price data from our price stream using an index (`.streamPair.i`). This is because we are simulating the arrival of these records dynamically, based on some delta time.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

This approach will provide us with:

![SpreadsD](https://github.com/hablapps/pairstrading/blob/5-Post/SpreadsD.JPG?raw=true)
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

And there we have it! **A perfectly plotted spread series in real-time**, ready to be utilized for further analysis and exploitation.

In this case we are using a [KX Dashboard](https://code.kx.com/dashboards/) to plot our data. We stream this data in one process to our local dashboard, which listens to that process and accesses the data to render visualizations.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

## What's left to start making profit?
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Finally, once we have our spreads accurately calculated and observe how our data is being updated second by second, we can **execute buy and sell orders when spreads discrepancies occur** based on some signal windows. Those windows, however, will be explored in greater depth in our next post about the Kalman Filter and its application in Pairs Trading.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

For now, it's crucial to clarify **our spread formulation and understand what it represents**. With this knowledge, we can identify instances where one asset is overpriced while the other is underpriced.

One might argue that our calculations are heavily influenced by past data, and that we rely too much on historical changes that **may not accurately reflect the present reality**. This is indeed a **valid concern**. To address this issue, we can utilize **the Kalman Filter**, a mathematical method for filtering noise and predicting states in a dynamic system. But we'll delve into the Kalman Filter in our upcoming posts as previously mentioned.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the second reference to a future Kalman filter post in this section. I think there's some redundancy with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true but I am figuring out how to put it. Because next post will explain two different things regarding pairs trading:

  1. Signal windows
  2. Kalman filter


Additionally, even though we fit our model with historical data, we could implement **a rolling window approach** where the linear regression is continuously updated. This would ensure that our model remains responsive to changes in the underlying data over time.

## The End

In conclusion, this post aims to provide a comprehensive overview that explains Pairs Trading from beginning to end, covering every aspect that may be relevant to understanding this topic and its intricacies in Q/kdb+.

Recapping, we have covered:

1. An introductory overview of the market as a whole.
2. An examination of cointegrated assets within the market.
3. Multiple Augmented Dickey-Fuller (ADF) tests on real assets.
4. A presentation of the pairs trading strategy itself.
5. A clear and guided explanation of spreads calculation, interpretation, and implementation in Q/kdb+.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
6. Additional knowledge necessary to master the strategy.

We aimed to demonstrate the capabilities of Q/kdb+ and its potential in a simplified manner that anyone can implement, particularly in the context of a widely used financial strategy. By doing so, we hope to make complex concepts more accessible and empower individuals to leverage these powerful tools in their own endeavors.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

We hope you found this information valuable and gained a good understanding of this financial tactic from both technical and economical perspectives. If you have any questions or need further clarification, don't hesitate to reach out.
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved

Be sure to stay tuned for more posts and updates on this blog to deepen your knowledge even further

Special thanks to [...] for [...]
Kokechacho marked this conversation as resolved.
Show resolved Hide resolved
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be unfinished...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complete the "special thanks", don't forget Javier.

Binary file added Spreads.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SpreadsD.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tfg18.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.