As suggested in my last post...
As a side note, I'm planning to make opposing robots this weekend. They will trade long and short positions in different sub-accounts.I've put together yet another robot. It will trade the same currency both long and short in separate sub-accounts. I'll have to wait until Monday or Tuesday to activate it.
A few points I feel are worth mentioning:
- I've been developing software and systems for my entire career -- I don't expect everyone can just snap together trading robots.
- There are rate limitations, position size limitations and margin use limitations built into a common framework used by all the robots I'm putting together.
Here is a chunk of common code used in each of my robots. Basically, I call the set of information relating a sub-account and a currency pair a trading context. Here is part of a function that gathers this context:
// ***************************************************
// Given strings representing the account to trade and
// the pair to be traded generate a trading context.
// ***************************************************
function getTradingContext(useacct,usepair)
{
// Determine account ID from it's name
// -----------------------------------
var acctid = 0;
for (id in accounts)
{
if ( accounts[id].name == useacct )
acctid = id;
}
if ( acctid == 0 )
{
write("Account name '" + useacct + "' not found!");
return null;
}
// Capture sub-account details in the trading context
// --------------------------------------------------
var myContext = accounts[acctid];
Once we have the account details we can determine various trading limitations. Here I use the account balance as well as manually controlled "reserve" and "release" values that determine default lot size and margin limit values:
// Calculate various balance values for various purposes
// -----------------------------------------------------
reserve = 0.00;
release = 0.00;
bal = myContext.balance;
// Avoid silly mistakes
// --------------------
if ( release > reserve )
release = reserve;
lsbal = bal - reserve; // lot balance
trbal = bal - reserve + release; // margin balance
ls = (lsbal/20) / 100000; // lots size
ml = trbal * 0.099; // margin limit
myContext.reserve = reserve;
myContext.release = release;
myContext.lsbal = lsbal;
myContext.lotsize = ls.toFixed(5);
myContext.trbal = trbal;
myContext.marginlimit = trbal * 0.095;
Before a trade can be made the current account margin usage will be compared to the margin limit determined above. When a trade is made the default size of the trade is the lot size determined above. Some other items loaded into the context are shown here:
// Capture currency pair details
// -------------------------------
myContext.usepair = usepair;
myContext.pair = pairs[usepair];
myContext.pipsize = pairs[usepair].pip;
myContext.spread = pairs[usepair].ask-pairs[usepair].bid;
// Set a spread limit for various currencies
// -----------------------------------------
myContext.spreadlimit = (4.26 * myContext.pipsize);
if ( usepair == "CHFJPY" )
myContext.spreadlimit = (2.26 * myContext.pipsize);
if ( usepair == "USDJPY" )
myContext.spreadlimit = (2.26 * myContext.pipsize);
if ( usepair == "EURUSD" )
myContext.spreadlimit = (2.01 * myContext.pipsize);
Including the currency pair information, especially the spread, is significant. For example, I do not let my robots trade when the spread is above certain values. This is because higher spreads are generally present when significant news events occur.
Later in my robots, in a function that is called when price changes are detected, I'll have something like the following:
longctx = getTradingContext("sub1",currentPair);
if ( longctx )
tradeLong(longctx);
shortctx = getTradingContext("sub2",currentPair);
if ( shortctx )
tradeShort(shortctx);
Generally, I'll use short term charts and limit robot operations to the opening of a new candle. This avoids needless processing but how you activate your trading functions is up to you. Notice how I can simply pass the context, as developed above, into a trading function? The trading functions have the job of deciding whether or not to open a position in a sub-account that it controls. It may or may not use all the details available to it.
There you go. While this isn't complete it is by far the majority of a basic robot framework. If you are a programmer you simply have to figure out the trading rules to apply and write one or more functions that embodies those rules. For example, you may want to apply indicators to a chart, examine previously opened orders, or even trigger an email signal.
Hey, as a bonus for reading this far, here is a function that examines current open orders to see how many fall within a price range. Basically, I use this function to make sure that my robots aren't able to accumulate positions around any particular price point. Notice that one of the parameters is the trading context developed above.
// ***************************************************
// How many orders are open between min an max prices?
// ***************************************************
function rangeOrderQty(ctx,min,max)
{
var qty=0;
for (ticket in activeOrders)
{
if ( activeOrders[ticket].accountId != ctx.id )
continue;
if ( activeOrders[ticket].pair != ctx.usepair )
continue;
if ( activeOrders[ticket].price >= min
&& activeOrders[ticket].price <= max )
qty++;
}
return qty;
}
Finally, the previous code is for the FxSpyder trading platform. This is what I'm using to write robots these days. I continue to trade via Oanada.