Broker Arbitrage: Trading with multiple brokers

Trading simultaneously with multiple accounts, brokers, exchanges, or data feeds allows broker arbitrage, i.e. exploiting prices differences of the same asset between different market places. Arbitrage opportunities appear for instance when Forex liquidity providers deviate from each other, or when market makers do not precisely follow the market. There is no central exchange for currencies and CFDs, so their prices vary from broker to broker. If the price differences temporarily exceed trading costs, you can collect risk-free profits.

Zorro S can simultaneously trade with up to 12 brokers or price data feeds. It allows trading strategies to compare currency or CFD prices between broker A and broker B, and enter a long position with the cheaper broker and a short position with the other. Here's the step by step setup and a code example for taking advantage of Forex/CFD price differences. But be aware that brokers dislike broker arbitrage practices, and may close accounts when they learn that they were exploited in this way.

Example:

// Simple broker arbitrage example ////////////////////////////

function tick()
{
  asset("EURUSD_A");
  var SpreadA = Spread, PriceA = priceClose(), 
    CommissionA = Commission*LotAmount/10000*PIP/PIPCost; // convert commission to price difference 
  asset("EURUSD_B");
  var SpreadB = Spread, PriceB = priceClose(), 
    CommissionB = Commission*LotAmount/10000*PIP/PIPCost;

  var Threshold = 1.5*(SpreadA+SpreadB+CommissionA+CommissionB); // arbitrage threshold
  var Difference = PriceA - PriceB;

  asset("EURUSD_A");
  if(NumOpenShort && Difference < 0)
    exitShort();
  else if(NumOpenLong && Difference > 0)
    exitLong();
  else if(!NumOpenShort && Difference > Threshold) // go short with the expensive asset
    enterShort();
  else if(!NumOpenLong && Difference < -Threshold) // go long with the cheap asset
    enterLong();

  asset("EURUSD_B");
  if(NumOpenShort && Difference > 0)
    exitShort();
  else if(NumOpenLong && Difference < 0)
    exitLong();
  else if(!NumOpenShort && Difference < -Threshold)
    enterShort();
  else if(!NumOpenLong && Difference > Threshold)
    enterLong();
}

function run()
{
  StartDate = EndDate = 2017;
  LookBack = 0;
  set(TICKS);
  History = "*.t1";
  assetList("AssetsArb.csv");
  asset("EURUSD_A");
  asset("EURUSD_B");
}
// Generate a multi-broker asset list ///////////////////////

#define LISTS "FXCM","Oanda"
#define ASSETLIST "AssetsMulti"

function main() 
{
  char OutName[NAMESIZE2]; // to store a temporary string
  strcpy(OutName,strf("History\\%s.csv",ASSETLIST));
  file_delete(OutName);
  string Name, Source = 0;
  while(Name = of(LISTS))
  {
    static char Dest[40000]; 
    file_read(strf("History\\Assets%s.csv",Name),Dest,0);
    if(!*Dest) return quit("Source not found!");
    string Pos = strchr(Dest,'\n');
// skip header line after first file
    if(!Source) Source = Dest;
    else Source = Pos;
    while(Pos) {
      Pos = strchr(Pos+1,',');
      if(!Pos) break;
// append list name to asset name
      strcatf(Pos,strf("_%s",Name));
      int i;
      for(i=0; i<11; i++) // find Symbol column
        Pos = strchr(Pos+1,',');
// append list name as source to symbol
      strcatf(Pos+1,strf("%s:",Name));
      Pos = strchr(Pos,'\n');
    }
    file_append(OutName,Source,0);
  }
}

See also:

Account list, Symbols, Brokers, TradeMode

► latest version online