Sari la conținut
  • intrări
    29
  • comentarii
    230
  • citiri
    1.158.761

Evolution and principles of the Intercross Arbitrage


TheEconomist

139.015 citiri

Va place aici?  

9 membri au votat

  1. 1.

    • Da
      9
    • Nu
      0

I. Evolution towards Intercross Arbitrage

 

1. Triangular Arbitrage

================

 

It is perhaps one of the most known arbitrage strategies learned in finance school. It consists in converting a given amount of cash in a currency thru some other currencies and back to original currency and getting profit, thus completing a currency ring transformation. It can be applied as an N-angular Arbitrage, when it has N currencies to deal with, but usually it's about three and this is why it's called Triangular Arbitrage. So, if we'd have some USD and market rates would allow arbitrage, it would mean, for example, to convert it to EUR, then to JPY and back to USD and have profit.

 

Example: we have $500

 

Market Rates:

 

EURUSD 1.3700/03

EURJPY 162.09/12

USDJPY 118.18/20

 

So we decide to:

 

1. sell USD to buy EUR (LONG EURUSD @ 1.3703) : 500 USD/1.3703 = 364.8836 EUR

2. sell EUR to buy JPY (SHORT EURJPY @ 162.09) : 364.8836 EUR * 162.09 = 59143.9827 JPY

3. sell JPY to buy USD (LONG USDJPY @ 118.20) : 59143.9827 / 118.20 = 500.37 USD

 

So, by making a conversion thru all the 3 currencies, we won 37 cents, meaning a ROE (Return on Equity) of 0.074%. Seems simple, huh?

 

The problem of Triangular Arbitrage is that it works only in EXCHANGE ENVIRONMENTS, where amounts of money are EFFECTIVELY EXCHANGED. Banks work in an EXCHANGE ENVIRONMENT. They are simultaneously in excess and need of liquidity. For example a bank has USD and needs EUR. It would then wire USD to another bank and get EUR wired back. It won't do a forex style LONG EURUSD, as it doesn't need a position on EURUSD, but the real EUR to make payments. Exchange houses are an example of an exchange environment. But, different than the one of the banks, they don't provide: tight spreads, electronic market and leverage. Going back to the trade example, when a bank finishes the three trades, it would have the profit in it's account, as every trade would cancel the previous trade result. One of the works that treats Triangular Arbitrage as Yukihiro Aiba's master thesis, "Triangular Arbitrage as an Interaction among Foreign Exchange Rates". However we forex traders don't have access to such an environment. We trade in the FOREX MARKET ENVIRONMENT and we can't do the Triangular Arbitrage as in theory, which remains only a simple theoretical base : our trades are independant, don't close each other. Once opened, we have the spread loss in our account. We must find the point where to close them. And this lead to step 2, the Fractional Products Inneficiency strategy.

 

2. Fractional Products Inneficiency

=========================

 

Fractional Products Inneficiency, as it was designed by its author, Michal Kreslik, on the end of 2006, beginning of 2007, is the application on FOREX of the Triangular or N-angular Arbitrage. Trade decisions of entry and exit are made on the Fractional Products Inneficiency (on short, FPI) swing.

 

On the earlier example, we could calculate a FPI like this

 

FPI = 1.3703 / 162.09 * 118.20 = 0.99925.

 

The no-arbitrage relationship would mean that FPI to be equal to 1. FPI less than 1, we can trade. In order to get profit we should wait for the FPI (CALCULATED THE SAME WAY, not changing bids with asks and vice-versa) to go to 1.0003 and so.

 

Michal's explanation of FPI strategy lacked:

a. a precise FPI calculation method as well as a precise ring establishment method (confusion between Buy-Sell-Sell and Sell-Buy-Buy currency rings almost last on all forum pages)

b. a link between FPI swing and results

c. embedding of spread costs in strategy

 

The most important things learned from Michal's FPI are:

a. hedging principle: each currency must be EQUALLY BOUGHT AND SOLD (by his words, "The Impeccable Hedge", although hedging in MetaTrader may be only good at its best);

b. the volume calculations for each operations, which is the pinnacle of his achievement.

 

Trying to overcome the mysteries and paradoxes of FPI explanation (as Michal said, "I hid the gold in many places for friends to find it"), I redesigned his strategy under the Intercross Arbitrage name.

 

 

3. Intercross Arbitrage

================

 

Before jumping to Intercross Arbitrage, let's first correct the ring confusion : which pairs should be bought and which pairs should be sold in a Kreslik currency ring ?

 

I consider the following:

 

Once the currencies are established (say EUR, USD, JPY), we imagine we are transforming the currency from one to the other

 

We have EUR.

1. We sell EUR to gain USD. EURUSD exists, we sell it.

2. We sell USD to gain JPY. USDJPY exists, we sell it.

3. We sell JPY to gain EUR. JPYEUR does not exist to sell it. EURJPY exists, and since we reversed the pair, we buy.

 

This can be done with n currencies. If one of the transformations cannot be done, for example neither PLNNOK nor NOKPLN exists, the entire ring is scrap, going to another combination. More about this on the Swap Arbitrage topic.

 

So, what's arbitrage?

A simple answer would be (for the complicated stuff, go see Wikipedia): "Simultaneously buying and selling the same asset at different prices to get immediate profit". Well, we don't have a New York EURUSD to arbitrage against a London EURUSD. So , how do we do it?

 

Let's return to the earlier example:

 

1. LONG EURUSD

2. SHORT EURJPY

3. LONG USDJPY

 

Let's translate it:

 

1. LONG EUR, SHORT USD

2. SHORT EUR, LONG JPY

3. LONG USD, SHORT JPY

 

We can see clearly that bought JPY in (2) is sold in (3) so JPY clears out, and what we have now is:

 

1. LONG EUR, SHORT USD

2. SHORT EUR

3. LONG USD

 

or:

 

1. LONG EUR, SHORT USD

2,3: SHORT EUR, LONG USD

 

So operations 2 and 3 are practically a virtual SHORT EURUSD. Now we have a secondary EURUSD to arbitrage against main, real EURUSD.

 

Not only the traded forex pairs have virtual counterparts, but also conceptual pairs may have only virtuals.

For example, let's say a broker doesn't trade GBPCHF at all.

 

GBPCHF could be made by: GBPUSD & USDCHF, but also by: GBPJPY & CHFJPY

 

We could actually have an arbitrage of "Virtual GBPCHF ask" against a "Virtual GBPCHF bid"

 

Market rates:

 

GBPUSD 2.0250/53

USDCHF 1.1988/91

GBPJPY 239.64/70

CHFJPY 98.78/83

 

Virtual GBPCHF ask means that we buy GBPCHF, so we must have:

LONG GBP, SHORT CHF , given by:

 

LONG GBP / SHORT XXX

LONG XXX / SHORT CHF

 

Similar, Virtual GBPCHF bid means that we sell GBPCHF:

 

SHORT GBP / LONG XXX

SHORT XXX / LONG CHF

 

By looking at the rates, we can spot the Virtual GBPCHF bid and ask:

 

Virtual GBPCHF ask:

 

LONG GBPJPY @ 239.70 (LONG GBP, SHORT JPY)

SHORT CHFJPY @ 98.78 (LONG JPY, SHORT CHF)

 

Virtual GBPCHF ask = 239.70 / 98.78 = 2.4266 as GBP/JPY / CHF/JPY = GBP/JPY * JPY/CHF = GBP/CHF

 

Virtual GBPCHF bid:

 

SHORT GBPUSD @ 2.0250 (SHORT GBP, LONG USD)

SHORT USDCHF @ 1.1988 (SHORT USD, LONG CHF)

 

Virtual GBPCHF bid = 2.0250 * 1.1988 = 2.4275 as GBP/USD * USD/CHF = GBP/CHF

 

So, this should mean we buy GBPCHF @ 2.4266 and sell it @ 2.4275 for 9 small CHF-sized pips as a potential. We should wait for the market to swing this and get our profit. But, how much do we pay for it?

 

First of all, let's calculate lotsizing to know exactly how much to trade.

 

The most remarcable of Michal Kreslik's achievements is lotsizing, how much to trade out of each pairs to keep hedging.

 

Suppositions:

 

1. USD 500 account equity

2. Maximum leverage : 200

3. Broker allows microlots (0.01) . I will explain later why microlots are important and how much they make the difference in hedging for the small guy.

4. We use 85% of available leverage . We allow a window of risk to cover for spreads and broker datafeed damage.

5. Size of a standard lot : 100000 units for USD and CHF denominated pairs, 70000 units for GBP denominated pairs

 

Calculus:

 

Total funds = 500 x 200 = 100000 USD

Available funds = 100000 x 85% = 85000 USD

 

We make 4 trades, so each one would be allocated around 85000/4 = 21250 USD:

 

The trades are:

 

LONG GBPJPY @ 239.70 (LONG GBP, SHORT JPY)

SHORT CHFJPY @ 98.78 (LONG JPY, SHORT CHF)

SHORT GBPUSD @ 2.0250 (SHORT GBP, LONG USD)

SHORT USDCHF @ 1.1988 (SHORT USD, LONG CHF)

 

One of the most difficult aspects is the one of the first trade. We must have a start point, so we must know how much is the first currency of the first trade in the account currency. It's simple now, as we must know how much is GBP in USD, but what if we'd had PLN or another exotic?

 

GBPUSD trades 2.0250/53, so we consider a rough GBP/USD = 2.02515

 

We have allocated 21250 USD for the trade, so this means 21250/2.02515=10,493.05 GBP. For a lotsize of 70000 GBP, we have 0.149 lots, rounded at two decimals 0.15 (normally not advisable to round up, but in this case the difference is very small) .

 

1. LONG 0.15 GBPJPY @ 239.70 (LONG GBP, SHORT JPY)

BOUGHT 10500 GBP = 0.15 x 70000 10500 GBP x 239.70 = 2516850 JPY SOLD

 

2.

Now we don't know how much CHF to short for the 2nd operation, but we know how much JPY to buy.

2516850 JPY / 98.78 = 25479.35 CHF. 25479.35/100,000 CHF = 0.2548 lots

Now we can use: 0.25 lots or 0.26 lots, depending on how much unhedged JPY may have:

 

a. SHORT 0.25 CHFJPY @ 98.78 (LONG JPY, SHORT CHF)

SOLD 25000 CHF = 0.25 x 100000 25000 CHF x 98.78 = 2469500 JPY BOUGHT (47350 JPY NET SOLD)

 

b. SHORT 0.26 CHFJPY @ 98.78 (LONG JPY, SHORT CHF)

SOLD 26000 CHF = 0.26 x 100000 26000 CHF x 98.78 = 2568280 JPY BOUGHT (51430 JPY NET BOUGHT)

 

So the a) version is better, as JPY unhedged side is smaller.

 

Since Virtual bids and asks calculations are independent, we could consider a new currency ring and start calculation from the beginning for the virtual ask, like we did before. Or we could use the GBP exposure and continue calculation. I am writing the 2nd version here to accustom readers with currency ring calculations.

 

10500 GBP / 70000 = 0.15 lots

 

3. SHORT 0.15 GBPUSD @ 2.0250 (SHORT GBP, LONG USD)

SOLD 10500 GBP = 0.15 x 70000 10500 x 2.0250 = 21262.5 USD BOUGHT (GBP completely hedged)

 

1417.5 USD / 100000 = 0.01 lots

 

4.

 

21262.5 USD / 100000 = 0.212 lots

 

a. SHORT 0.21 USDCHF @ 1.1988 (SHORT USD, LONG CHF)

SOLD 21000 USD = 0.21 x 100000 21000 x 1.1988 = 25174.8 CHF BOUGHT (262.5 USD NET BOUGHT, 174.8 CHF NET BOUGHT) ;

TOTAL UNHEDGED AMOUNT = (47350 JPY / 118.38 as USDJPY rate = 399.98) + 262.5 USD + (174.8 CHF = 145.81 USD) = 808.29 USD

 

b. SHORT 0.22 USDCHF @ 1.1988 (SHORT USD, LONG CHF)

SOLD 22000 USD = 0.22 x 100000 22000 x 1.1988 = 26373.6 CHF BOUGHT (737.5 USD NET SOLD, 1,373.6 CHF NET BOUGHT) ;

TOTAL UNHEDGED AMOUNT = (47350 JPY / 118.38 as USDJPY rate = 399.98) + 737.5 USD + (1373.6 CHF = 1145.81 USD) = 2283,29 USD

 

So the a) trade is chosen.

 

Still, the example shows a 808.29 USD unhedged volume, which slips with a 0.08 USD/pip on total position fluctuation

 

 

II. Exposure under assumptions of using and not using microlots

 

Exposure is generated from the simple fact that currencies obtained or sold during SELL and BUY operations cannot be offset due to the fact that the lotsize cannot mimic this value.

 

For example we want to hedge USD in the following example by buying USDJPY.

 

BUY 0.2 EURUSD @ 1.33

We are LONG 20000 EUR, SHORT 26600 USD

 

1.Using microlots (0.01)

 

We could:

a. LONG 0.26 USDJPY @ 121

We are SHORT 13000 USD, LONG 3146000 JPY

USD exposure: SHORT 26600-26000 = 600 USD

 

b. LONG 0.27 USDJPY @ 121, LONG 3267000 JPY

We are LONG 27000-26600 = 400 USD

 

Given the fact we always choose for hedging the appropriate lotsize, the maximal unhedged volume may go up to 500* units (500 USD, 500 EUR, 500 GBP and so on), being also the indifference point where it doesn?t matter if you hedge by choosing upper or lower volume.

 

2. Using mini lots (0.1)

 

We could:

a. LONG 0.2 USDJPY @ 121

We are SHORT 20000 USD, LONG 2420000 JPY

USD exposure: SHORT 26600-20000 = 6600 USD

 

b. LONG 0.3 USDJPY @ 121, LONG 3630000 JPY

We are LONG 30000-26600 = 3400 USD

 

Given the fact we always choose for hedging the appropriate lotsize, the maximal unhedged volume may go up to 5000* units (5000 USD, 5000 EUR, 5000 GBP and so on), being also the indifference point where it doesn?t matter if you hedge by choosing upper or lower volume.

 

*Note: 500 or 5000 on the assumption that a full lot is 100000 units.

 

1. Unhedged volume is also a function of contracts traded and pair configuration.

 

If there are 3 contracts traded, one currency will be completely hedged, 2 incompletely hedged.

 

Example 1:

 

EURUSD

EURGBP

GBPUSD

 

EUR will be completely hedged, GBP and USD not completely.

 

If there are 4 contracts, 2 or 3 currencies may be incompletely hedged:

 

Example 1:

 

USDGBP

USDJPY

EURGBP

EURJPY

 

Only GBP and JPY not completely hedged.

Example 2:

 

EURGBP

EURCHF

GBPUSD

USDCHF

 

 

GBP, CHF and USD not completely hedged.

 

The hedged currencies are the ones that are being bought and sold being the first currency in the involved pairs.

 

2. Proportional unhedged volume, proportional equity

 

Say a $500 account trades at 200 leverage, using 80% of available margin, USING MICROLOTS.

Used funds = 500x200x80% = 80.000 USD. Say we have 4 trades. Maximum exposure is 500 units each. We would have exposure of 500 GBP, 500 EUR, 500 USD (wouldn?t happen in practice, only in theory; I considered the 3 currencies starting from GBP, the most expensive).

So ~1500 EUR unhedged currency, about 1,875% of total volume

 

Say the arb is 4 USD pip high. The unhedged part of 1500 EUR values ~ 2000 USD.

The 4 pips correspond to 80000 USD, meaning a profit of 8 x 4 = 32 USD

There would be needed a bad luck of 160 USD pips on the aggregated volume of the 3 unhedged currencies to wipe out the profit.

 

 

WITHOUT MICROLOTS, maximal exposures would be 5000 GBP, 5000 EUR, 5000 USD ..~15000 EUR = 18,75%

Unhedged part, ~ 20000 USD

Only 16 USD pips bad movement on the 3 currencies needed to wipe out profit.

 

 

But if the account is $5000, maximal exposure is the same as before.

Profit comes on 800000 USD = 320 USD

So 160 pips needed to wipe out profit.

 

Without microlots, risks can be brought down from $5000 in account equity? Sorry, that?s it.

 

III. Completing the Fractional Product Inneficiency : Potential, Costs and Required

 

One of the greatest FPI drawbacks was the fact you had to rely only on FPI value to initiate trade or close. There was no way to know it was enough except for closing when you could have watched the total profit. But how about the entry point ? Would just a fixed value of FPI 0.9997 be enough as entry criteria ?

 

Being given the fact that we are virtually long and short on the same pair, we know that these "assets" can't stay forever on this position. Having the same meaning as the pair they represent, they have to be, randomly, on both sides of it, so, what gives now a virtual bid will make a virtual ask in the days to come and vice versa.

 

We have to answer the following questions:

 

1. How much is for real for the gap between virtual bid and virtual ask ?

Created gap is in the Virtual pair secondary currency. We must convert it to account currency for correct comparison.

 

2. How much do we pay for this stuff?

Different trade results are in different currencies, costs must be brought to a single currency.

 

3. How much potential needs a trade group in order to cover spreads, slippage and have decent profit?

 

1. How much is the real gap between virtual bid and virtual ask?

==============================================

 

Even if the synthetic pair has a virtual/real bid and a virtual/real ask, the atoms, meaning the trade subgroups that create the buy-side and the sell-side have also another real/virtual of their own. Like in the GBP/CHF example earlier,

 

looking at the buyside atom:

 

LONG GBPJPY @ 239.70 (LONG GBP, SHORT JPY)

SHORT CHFJPY @ 98.78 (LONG JPY, SHORT CHF)

 

It's true that traded prices make up the Virtual ask, but the close prices for each trade make up the bid of the entire group.

 

Let the TakenBid and TakenAsk be the Virtual bid and ask prices;

if aask and abid being the mirror (close prices),

CrossPair the pair you arb on;

 

then you can write:

 

Pips = (TakenBid-aask) * multiplicator + (abid - TakenAsk) * multiplicator , where multiplicator is usually 10000 or 100 for JPY ended pairs (10^n , where n is the number of decimals)

 

Now the pips are denominated in the second currency, meaning CHF.

 

We want to convert it to our account currency, USD, and we'd better do that via USDCHF rate.

 

 

2. How much do we pay for this stuff ?

============================

 

And I'm asking here:

 

How much is a tick of the account currency on a standard lot?

 

With MarketInfo you can find out how much is a tick on a given currency pair:

 

MarketInfo(contract, MODE_TICKVALUE) , and , for a USD account on EURUSD test gives 10, because you have 10 USD/pip trading EURUSD.

 

What if you have the account denominated in EUR? Because your account currency is EUR, applying the same MarketInfo("EURUSD",MODE_TICKVALUE) won't give you that 10 again... and if you don't have any XXXEUR pair on hand, what you could do is multiply the MarketInfo result by EURUSD, cancelling the correction embedded in MarketInfo.

 

A short route to appendix now: Appendix is what some MetaTrader brokers add to currency pairs. For example, mini InterbankFX accounts have that "m" appended to the end of currency pair, like EURUSDm. To get the appendix, use BcLib function GetSymbolsAppendix(). Just a simple call like appendix=GetSymbolsAppendix() and your strategy would then run on any broker without other modifications due of this. Call it once per EA, in the init(), takes some time!

 

Now, the implementation of tick of the account currency in BcLib is this:

 

double GetTickDenominator(string appendix)
 {
 string acctcurrency=AccountCurrency();
 double res=0;
 if (acctcurrency=="USD")
    res=MarketInfo(StringConcatenate("EURUSD",appendix),MODE_TICKVALUE);
 if (acctcurrency=="EUR")
    res=MarketInfo(StringConcatenate("EURUSD",appendix),MODE_TICKVALUE)*MedPrice(StringConcatenate("EURUSD",appendix));
 if (acctcurrency=="GBP")
    res=MarketInfo(StringConcatenate("EURGBP",appendix),MODE_TICKVALUE)*MedPrice(StringConcatenate("EURGBP",appendix));     
 if (acctcurrency=="CHF")
    res=MarketInfo(StringConcatenate("GBPCHF",appendix),MODE_TICKVALUE);
 if (acctcurrency=="JPY")
    res=MarketInfo(StringConcatenate("USDJPY",appendix),MODE_TICKVALUE);            
 return(res);
 }

 

*Note: the MedPrice function just returns a simple (bid+ask)/2

 

Now let's head back to our account currency evaluation:

 

For each contract traded inside, we calculate it like this:

 

pipcost=MarketInfo(contract,MODE_SPREAD)*MarketInfo(contract,MODE_TICKVALUE)/GetTickDenominator(appendix);

 

the volumes are equivalent, no need to think about them!

 

Now we can see that the implementation of GetTickDenominator was correct. Supposing our contract was EURUSD trading at about 1.37. GetTickDenominator would give us a 10, since 10 EUR won on a EUR account is the same as 10 USD won on a USD account. MarketInfo("EURUSD",MODE_TICKVALUE) would return about 7.2 (would have been 10 if account would have been USD denominated) ; GetTickDenominator would return 10, so the result would be around 2.16, or 3/1.3700 .

 

3. How much potential needs a trade group in order to cover spreads, slippage and have decent profit?

=========================================================================

 

Problem of the costs is that the costs are dynamic. The spread is fluctuating, and the costs once with it. Here there is freedom of choice.

We could calculate the Required potential to include the costs + a percent of the costs + a fixed amount of pips to compensate for slippage and spread fluctuations...

 

http://img402.imageshack.us/img402/3323/virtualbidsandaskstg1.jpg

 

IV. Implementation

 

MetaTrader or Reuters Dealing ? :biggrin:

http://img77.imageshack.us/img77/1440/arbtraderfigtingthemarkcn4.jpg

 

*Note that the displayed bids and asks will be the ones on the best bids and asks, even if a trade group is placed and old "lesser" bid and ask atoms are now the best ones.

 

1. How are the pairs generated

=======================

 

MetaTrader doesn't have a function to enumerate available currencies and pairs. This is overcome in BcLib by the following mechanism:

The TestCurrencies[] , which includes 15 currencies: "EUR","USD","GBP","JPY","CHF","AUD","CAD","NZD","HKD","THB","NOK","SEK","DKK","PLN","TRY".

If you want to add more currencies to be tested, just use AddCurrencyToTest(currency) , before going further.

 

By calling GetCurrenciesAndPairs(Appendix) you get the used currencies and used pairs in UsableCurrencies[] and UsablePairs[] ; the numbers of currencies and pairs are indicated in CurrenciesNo and PairsNo integers. This procedure will test the currencies of the TestCurrencies[] agains each other. When one currency pair exists, it is aded to UsablePairs[], and the two currencies that make it are added, if not already there, in UsableCurrencies[].

 

In order to know exactly what rates appear on screen and how are they calculated, BcArb creates a series of crosslists, by combining every 2 currencies with a 3rd-one. What it gets, is, all the atoms that can be used for buy or sell that emulate a currency pair (this example is generated on WHC's Metatrader):

 

EUR/USD EURUSD GBP21 JPY22 CHF22 AUD21 CAD22 NZD21

EUR/GBP EURGBP USD22 JPY22 CHF22 AUD22 CAD22

EUR/JPY EURJPY USD21 GBP21 CHF21 AUD21 CAD21 NZD21

EUR/CHF EURCHF USD21 GBP21 JPY22 AUD21 CAD21 NZD21

EUR/AUD EURAUD USD22 GBP21 JPY22 CHF22 CAD22 NZD22

EUR/CAD EURCAD USD21 GBP21 JPY22 CHF22 AUD21 NZD21

EUR/NZD EURNZD USD22 JPY22 CHF22 AUD21 CAD22

GBP/USD GBPUSD EUR11 JPY22 CHF22 AUD21 CAD22

USD/JPY USDJPY EUR11 GBP11 CHF21 AUD11 CAD21 NZD11

USD/CHF USDCHF EUR11 GBP11 JPY22 AUD11 CAD21 NZD11

AUD/USD AUDUSD EUR11 GBP11 JPY22 CHF22 CAD22 NZD21

USD/CAD USDCAD EUR11 GBP11 JPY22 CHF22 AUD11 NZD11

NZD/USD NZDUSD EUR11 JPY22 CHF22 AUD11 CAD22

GBP/JPY GBPJPY EUR11 USD21 CHF21 AUD21 CAD21

GBP/CHF GBPCHF EUR11 USD21 JPY22 AUD21 CAD21

GBP/AUD GBPAUD EUR11 USD22 JPY22 CHF22 CAD22

GBP/CAD GBPCAD EUR11 USD21 JPY22 CHF22 AUD21

GBP/NZD EUR11 USD22 JPY22 CHF22 AUD21 CAD22

CHF/JPY CHFJPY EUR11 USD11 GBP11 AUD11 CAD11 NZD11

AUD/JPY AUDJPY EUR11 USD21 GBP11 CHF21 CAD21 NZD21

CAD/JPY CADJPY EUR11 USD11 GBP11 CHF21 AUD11 NZD11

NZD/JPY NZDJPY EUR11 USD21 CHF21 AUD11 CAD21

AUD/CHF AUDCHF EUR11 USD21 GBP11 JPY22 CAD21 NZD21

CAD/CHF CADCHF EUR11 USD11 GBP11 JPY22 AUD11 NZD11

NZD/CHF NZDCHF EUR11 USD21 JPY22 AUD11 CAD21

AUD/CAD AUDCAD EUR11 USD21 GBP11 JPY22 CHF22 NZD21

AUD/NZD AUDNZD EUR11 USD22 JPY22 CHF22 CAD22

NZD/CAD NZDCAD EUR11 USD21 JPY22 CHF22 AUD11

 

In order to obtain the list, just call CreateCrosslistsTable(Appendix) from BcArb. The list is contained in CrosslistsTable[] and its length is specified by the CrosslistsNo integer.

 

Note that, if one pair has only one atom, it won't appear in the list, as one atom does not have a counterpart to be arbitraged to.

 

Let's analyse a line:

 

EUR/USD EURUSD GBP21 JPY22 CHF22 AUD21 CAD22 NZD21

 

The first word of the line specifies the cross: EUR/USD

The atom which contains the pair itself is the real one; the others are virtuals;

 

GBP21 = EURGBP & GBPUSD;

In combination with the first currency of the cross (EUR), the combined currency (GBP) appears on the 2nd position

In combination with the second currency of the cross (USD), the combined currency (GBP) appears on the 1st position

 

In this example, EURGBP is Pair1 and GBPUSD is Pair2.

 

Calculating cross virtual bid and ask

===========================

 

If the atom is a real pair, virtual bid and ask are pair's bid and ask. If not:

 

1. We analyse the indexes (what comes after the currency, e.g. 2 and 1 after GBP), and we establish buy and sell prices for Pair1 and Pair2.

 

a. First index

 

Case 1:

 

Pair1.buy=bid;

Choice for buy : Short;

Pair1.sell=ask;

Choice for sell : Long;

 

Case 2:

 

Pair1.buy=ask;

Choice for buy : Long;

Pair1.ask=bid;

Choice for sell : Short;

 

b. Second index

 

Case 1:

 

Pair2.buy=ask;

Choice for buy : Long;

Pair2.sell=bid;

Choice for sell : Short;

 

Case 2:

 

Pair2.buy=bid;

Choice for buy : Short;

Pair2.sell=ask;

Choice for sell : Long;

 

 

Now, once we established the prices for both pairs upon what we want to do with the cross, we calculate the cross price:

 

Case 11:

 

cross bid=(1/Pair1.sell)*Pair2.sell;

cross ask=(1/Pair1.buy)*Pair2.buy;

 

Case 12:

 

cross bid=(1/Pair1.sell)/Pair2.sell;

cross ask=(1/Pair1.buy)/Pair2.buy;

 

Case 21:

 

cross bid=Pair1.sell*Pair2.sell;

cross ask=Pair1.buy*Pair2.buy;

 

Case 22:

 

cross bid=Pair1.sell/Pair2.sell;

cross ask=Pair1.buy/Pair2.buy;

 

This job is automatically done by BcArb's GetAtomData()...

 

Transforming units to lots

===================

 

Lotsize calculations are based on volume calculations on bought and sold amounts of currency. DO NOT PRESUME LOTS ARE 100000 FOR EACH CONTRACT!

Use always the UnitsToLots function, as it is implemented in BcLib. As it is implemented now, it will always choose the appropriate volume, except for 0, which will never be chosen, if it may be appropriate volume (for example on a broker that doesn't allow microlots we transform 3000 units on EURUSD. Appropriate volume is 0, yet answer will be 0.1 (for 10000).

 

double UnitsToLots(double units,string contract)
 {
 double dlotsize=MarketInfo(contract,MODE_LOTSIZE);
 double mag=MarketInfo(contract,MODE_LOTSTEP);
 double mini=MarketInfo(contract,MODE_MINLOT);
 double big=1/mag;    
 double size=dlotsize/big;
 double dlots0,dlots1,back0,back1;
 dlots0=NormalizeDouble(units/size,0)*mag;
 dlots1=dlots0+mag;
 back0=dlots0*big*size;
 back1=dlots1*big*size;
 if (back1-units<units-back0)
   {
    if (dlots1<mini)
      return(mini);  
    else  
      return(dlots1);
   }
 else
   {
    if (dlots0==0)
       return(mini);
    else
      {
       if (dlots0<mini)
         return(mini);
       else
         return(dlots0);
      }//else if (dlots0==0)
   }//else if if (back1-units<units-back0)
 }  

 

 

2. Implementation details

===================

 

These are ArbTrader_script's working parameters (it is a script, put it in the \scripts folder)

 

extern int DisplaySetup=2;

extern int Tryouts=5; //0 for unlimited tryouts, don't put that!

extern int MarginUsed=85;

extern int Slippage=100;

extern int MaxTickDelay=30;

extern double TakePipsRatio=50;

extern double TakePipsFixed=2;

extern double TakePipsCloseRatio=50;

extern double TakePipsCloseFixed=2;

extern bool EnableFreshness=true;

extern bool EnableLiveTest=false;

extern int DontRepeatLiveTestForSecs=300;

extern bool AllBips=False;

 

Do not change the display type; 1 may work, but not tested.

Tryouts means how many times it will try opening a trade.

MarginUsed is the used ratio from available leverage;

Slippage is very high; I set it like that in order to leave some space for opening last trade; it's not good to remain unhedged while losing time trying to open last;

MaxTickDelay works if Freshness is enabled; All the pairs last quotes must be fresher than MaxTickDelay, otherwise trade won't be triggered;

TakePipsRatio and TakePipsFixed establish the Potential for opening ; TakePipsClose and TakePipsCloseFixed establish the Potential for closing (close moment is calculated like a potential, too);

EnableFreshness enables Freshness test;

EnableLiveTest is good to be on false; if not, before triggering trades at full scale , it will do them at the smallest tradable amount and close them. If one crashes, the big trades won't be triggered; The program remembers last arb data ; so if a new test is to come, generating further account drainage, this will be prevented if it comes in DontRepeatLiveTestForSecs seconds;

AllBips is an older setting; On previous MetaTrader versions, using a sound (from dll) that didn't exist, a system error bip was produced; This bip was to be enabled on all yellow lightings if AllBips was true; Otherwise, Cepstral Amy's voice should to be heared when arbitrages where entered and closed. (place ArbEnter.wav and ArbClose.wav in C:\Windows)

 

V. Conclusions

 

Both FPI and Intercross Arbitrage are versions of the hardest strategy to understand or implement. Problem is, the result doesn't seem to cover the huge effort for understanding and implementing it. The strategy is cripled by one of the pairs going off quotes... It stays behind the others, generates arbitrage, then can't be traded for minutes. When it's traded, it's already on loss... Plus that trading occurs rarer than seldom. But, despite this, the strategy remains practically the single arbitrage strategy that can be applied with forex alone, without using futures.

34 Comentarii


Comentarii Recomandate



Greetings,

Some excellent work you have here.

I tried this on MBTrading's MT4 Demo. They charge a commission but have very low spreads. Throws up an error box ..

Swap2Interest ***** swap type 2 not implemented

Appreciate it if you can help.

Thanks

Blair

 

Hi Blair,

 

Well, we have to find the formula. I think I had an account and it expired. Could you make some trades and post the swap after a day ? Also post the swap type,

long and short for the symbol (right click the Market Watch, Symbols, navigate to the symbol, Properties)

 

Regards,

Bogdan

Link spre comentariu
Vizitator Blair

Postat

Thanks Bogdan,

Formula is Volume (in USD) * [ (Premium Rate / 100) / 360 ]

Rollover at 5pm EST after 2 days, no swap if closed before then.

Please see http://mbtrading.com/forexRolloverPremRates.aspx

 

If the fills on their MT4 are anything like the Navigator platform

then they are brilliant. I have traded with them for 2 years and

what you see is what you get. On the downside their premium

rates are horrible.

Is this what you need?

 

Blair

Link spre comentariu
Thanks Bogdan,

Formula is Volume (in USD) * [ (Premium Rate / 100) / 360 ]

Rollover at 5pm EST after 2 days, no swap if closed before then.

Please see http://mbtrading.com/forexRolloverPremRates.aspx

 

If the fills on their MT4 are anything like the Navigator platform

then they are brilliant. I have traded with them for 2 years and

what you see is what you get. On the downside their premium

rates are horrible.

Is this what you need?

 

Blair

 

Well Blair, seems they were nice enough to publish a formula. Of course, is the general formula for one day interest. But the function needs data to compute the interest value - and it gets them MarketInfo() : the swap type (MODE_SWAPTYPE), the long swap (MODE_SWAPLONG) and the short swap (MODE_SWAPSHORT), so it is used to convert swap data to interest on any fx pair and any trade direction. So I need to know some data. Run this script on several currency pairs, until you get the printed message "Swap type on .... is 2".

 

int Start()

{

Print("Swap type for ",Symbol()," is ",MarketInfo(Symbol(),MODE_SWAPTYPE));

Print("Long swap : ",MarketInfo(Symbol(),MODE_SWAPLONG));

Print("Short swap : ",MarketInfo(Symbol(),MODE_SWAPSHORT));

return;

}

 

When you get that message, make a trade on that pair on your demo and leave it for a day, until it produces swap. I'd like it not to be Wednesday so we're not confused about the triple swap. Then tell me the traded pair, direction (buy or sell) , lot size you traded, and the swap on the swap column, also what the script said at Long swap and Short swap. I'll compute the formula and update the Swap2Interest_Volume function.

 

Regards,

Bogdan

Link spre comentariu
Vizitator Blair

Postat

Thanks and I will do that.

Now here is the next stupid question. You have to love them!!

So that I could practice I enabled the swap2Interest function.

Now I had plenty of Yellow on the screen but nothing happening.

On about line 440 of arbtrader_script it reads

 

if (bigpips>=costhere*(100+TakePipsRatio)/100+TakePipsFixed&&costhere>0||costhere<0)

when cost < requested we get a yellow but bigpips appears to be the potential.

I assume bigpips is pips that we all know rather than the fractional variety that

have snuck in.

What am I missing here?

cheers

Blair

Link spre comentariu
Thanks and I will do that.

Now here is the next stupid question. You have to love them!!

So that I could practice I enabled the swap2Interest function.

Now I had plenty of Yellow on the screen but nothing happening.

On about line 440 of arbtrader_script it reads

 

if (bigpips>=costhere*(100+TakePipsRatio)/100+TakePipsFixed&&costhere>0||costhere<0)

when cost < requested we get a yellow but bigpips appears to be the potential.

I assume bigpips is pips that we all know rather than the fractional variety that

have snuck in.

What am I missing here?

cheers

Blair

 

Hehe,

I don't know if you'll be able to get arbs there. I remember I did the test. You have a yellow if potential is positive i.e. Best bid > best ask. If the fx would work in an exposure fashion, that is, when last trade would be completed, trades would end in profit, it would be fine, but unfortunately you have always a fluctuating spread cost, because it's not enough to have synthetic best bid > synthetic best ask : after you close, you pay all spreads to the last dime. There is also a huge difference between cost and requested. Because there is not enough to just cover the cost, the requested has to make enough for slippage and your profit. And by the way I saw the things in MB Trading at that time, there is almost no chance to get an arb traded. Bigpips is the difference between Best ask and best bid, transformed in the account currency.

 

P.S. MT4 is an expired product. There is no way to be used for successful arbing. Not on the fx, and probably not on futures either. I'm waiting to see MT5. If it will include a multiasset backtester and a options, besides fx and some futures, it would be rockin'. Lots of things that were just thought about in MT4, but never tested, and also of things that fx traders never even think they might exist, might be now on MT5. And that means pair trading, that was impossible to backtest on MT4, with its all possible variations, from EURUSD/USDCHF to fx/futures triggered by events, or underlyings/options like gamma scalping for instance. I will probably restructure the entire blog, keep the best and delete the rest, and move on to multiasset strategies on MT5, cause I lost too much time because of MT4.

 

Regards,

Bogdan

Link spre comentariu
Vizitator Guest

Postat

Thanks for that

So you want the potential to be worth 1.5 times

the cost plus a few pips before taking the trade?

That would have to be a certainty if you got it filled.

Are you saying that MB is no good because their spreads are too

tight? They still do not have MT4 working anyway. I was going to

use the API for their other platform. You are doing some very good

work here.

Blair

Link spre comentariu
Thanks for that

So you want the potential to be worth 1.5 times

the cost plus a few pips before taking the trade?

That would have to be a certainty if you got it filled.

Are you saying that MB is no good because their spreads are too

tight? They still do not have MT4 working anyway. I was going to

use the API for their other platform. You are doing some very good

work here.

Blair

 

Thanks Blair,

Well, MB Trading gives a true ECN feed. And in that market there are big boys with hedge fund platforms that have not only level II access , which means lower spreads, due to the possibility of being filled, but also millisecond latency. How can we compete with that? Most likely, we don't. Solutions : 1. we either attempt fx arb with their API or a retail low-latency platform, like Neoticker, or wait for this new MT5 and speed towards more statistical, higher latency arbs. Me and my friends would have liked to test the fx-futures arb on MB Trading. But their demo is pretty horrible: futures plays canned data, 2 weeks old, so we had to dump it, at least for the moment. So now I'm waiting to see if MT5 raises to my expectations and becomes that all-in-one trading platform that offers just about everything besides latency,

so there won't be any limit in terms of assets, programming language or backtesting facilities, only execution speed to remain faulty, and some of the assets to be broker imitations like CFDs. So then I could set my eyes on various multiasset stat arb strategies, the last that are available to retail traders, but are just shadowed by the lack of platforms for backtesting and trading them.

 

Regards,

Bogdan

Link spre comentariu
Vizitator Blair

Postat

I am always suspicious of Metatrader brokers. It appears geared for the bucket shops. After all, they are the customers. Having access to CFDs and other

instruments would be great. How about Interactive Brokers they seem to have a lot going for them and your fill on futures would be much better than the majority, but then there is the problem of lot size. I have to agree that we have to boldly go where no one has gone before. Here is an idea. I have traded thin futures contracts in the past. The reason being that their is less noise and the slippage was not important as I was trading for the medium term. These instruments don't attract the big boys so that is one really big plus. As I get my head around what you are doing here I am thinking of opportunities. So lets say you look for a play on a thin Index futures vs an ETF or another index. You target the thin market first then fill on the more liquid one. You can I don't think you need too much backtesting to cover these opportunities and I am guessing that the thin market scare the big boys away.I am attracted to it because I have been there before. So what if it only does 2000 a day, that is more than enough I think. Anyway the more I think about this the more I like it. For me it is much easier than the more complex instruments like options etc.

 

As for MB I am thinking that the opportunities might be there if you lower your horizon. The fills on the other platform are at the bid/ask has been my experience so I will do some more testing. The MT4 demo platform is finally showing something like a stable feed, at times, so good for me to get some experience on. I will do some work on the API just in case. Easy really as you have done all the hard work.

Cheers

Blair

Link spre comentariu
Vizitator Blair

Postat

There are commercial products available that can do the orders to MB so I am not going to bust a gut with their SDK. Also I use mostly use delphi and java so that is another impediment.

Anyway I changed some params to force entries on MB demo and see how it went. It tried to do an arb against the sek which was so thin at the time that it fell over and got left with a euro position. This brings me to the point of my post which follows on from the previous one. Sorry for clogging up your blog. :) Anyway my suggestion is to always fill the thinner legs first on any arb strategy, entry and exit. You could maintain a ranked list using your quote refresh algorithm or access a volume field and so on. I have not gotten through reading all of the code yet but I shall make a determined effort so as to not bother you with dumb questions.

Blair

Link spre comentariu

Vizitator
Adaugă un comentariu...

×   Alipit ca text avansat.   Alipește ca text simplu

  Doar 75 emoji sunt permise.

×   Linkul tău a fost încorporat automat.   Afișează ca link în schimb

×   Conținutul tău precedent a fost resetat.   Curăță editor

×   Nu poți lipi imagini direct. Încarcă sau inserează imagini din URL.

×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.