Caută în comunitate
Afișez rezultate pentru tagurile 'Intercross Arbitrage'
Găsit 1 rezultat
-
Evolution and principles of the Intercross Arbitrage
TheEconomist a postat o intrare blog în TheEconomist's Forex Arbitrage Blog
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 ? 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.