Error margin in FT?

How to create strategies and indicators
Message
Author
Matt_mm
Posts: 17
Joined: Sat Jun 06, 2009 8:40 pm

Error margin in FT?

#1 Postby Matt_mm » Wed Jul 01, 2009 11:23 pm

Hi,

I've come accross a discrepency in testing that seems may be imposed incorrectly by FT. Either that or there's an error in my code that I can't see.

The strategy opens multiple positions each day alternating between buy and sell. The error margin is clear in the following example:

I set take profit and stop to 100 pips (keeping in mind the spread). Over many thousands of trades I expected 50% win and loss with the account losing money from the spread. Instead the result was 48% win 52% loss. I then redid the test in reverse so long positions where now short and vica versa. The result was the same 48% win, 52% loss. This appears to be an error as reversing the direction of the trades should result in the opposite win and loss %. Does FT impose a bias towards losing trades?

My code:


Code: Select all

library RandomStacking_v3Long;

uses
  SysUtils,
  StrategyInterfaceUnit,
  TechnicalFunctions,
  DateUtils;

var
  Currency: PChar;
  Spread: integer = 6;
  timeframe: integer = PERIOD_H1;
  TradesPerDay: integer = 4;
  PositionNumber: integer = 1;
  SomeInfo: PChar;
  BasePosition: double = 0.1;
  StopLoss: integer = 100;
  TakeProfit: integer = 100;
  EntryDistance: integer = 0;
  OrderDirection: integer = 1;
  HourOpened: integer = 0;

procedure InitStrategy; stdcall;
begin
  StrategyShortName('Random-LongStart_v3');
  StrategyDescription('Strategy with random entry probability to test stacking probabilities.');
  RegOption('Currency', ot_Currency, Currency);
  ReplaceStr(Currency, 'GBPJPY');
  RegOption('Timeframe', ot_Timeframe, timeframe);
  RegOption('Spread', ot_Integer, Spread);
  RegOption('Trades per day (Max 11)', ot_Integer, TradesPerDay);
  SetOptionDigits('Trades per day (Max 11)', 0);

  AddSeparator('Basic positions options');
  RegOption('Open position this distance from market', ot_Integer, EntryDistance);
  SetOptionDigits('First position distance from market', 0);
  RegOption('Take Profit', ot_Integer, TakeProfit);
  SetOptionDigits('Take Profit', 0);
  RegOption('Stop Loss', ot_Integer, StopLoss);
  SetOptionDigits('Stop Loss', 0);
  end;

procedure DoneStrategy; stdcall;
begin
  FreeMem(SomeInfo);
  FreeMem(Currency);
end;

procedure ResetStrategy; stdcall;
begin

end;

procedure GetSingleTick; stdcall;
var
  time: TDateTime;
  OrderHandle: integer;
  EntryPrice: double;
  ProfitPrice: double;
  StopPrice: double;
begin
  if Symbol <> Currency then
  begin
    exit;
  end;
  time := iTime(Symbol, PERIOD_H1, 0);
  //max of 11 trades per day
  if (TradesPerDay > 11) then
  begin
    TradesPerDay := 11;
  end;
  //if (order direction is short) and (open positions a multiple of 2 hours) and (hasn't been opened this hour) and (only opens the number of positions specified in TradesPerDay)
  if ((OrderDirection = 0) and (Hourof(time) = (PositionNumber * 2)) and (Hourof(time) > HourOpened) and (PositionNumber <= TradesPerDay)) then
  begin
    EntryPrice := Bid - (EntryDistance*Point);
    ProfitPrice := EntryPrice - (TakeProfit*Point);
    StopPrice := EntryPrice + ((StopLoss+Spread)*Point);
    //specifies if Sell or SellStop should be used
    if (EntryDistance = 0) then
    begin
      SendInstantOrder(Symbol, op_Sell, BasePosition, StopPrice, ProfitPrice, '', PositionNumber, OrderHandle);
    end
    else
    begin
      SendPendingOrder(Symbol, op_SellStop, BasePosition, StopPrice, ProfitPrice, EntryPrice, '', PositionNumber, OrderHandle);
    end;
    OrderDirection:= 1;
    HourOpened:= PositionNumber * 2;
    PositionNumber := PositionNumber +1;
  end;
  //if (order direction is long) and (open positions a multiple of 2 hours) and (hasn't been opened this hour) and (only opens the number of positions specified in TradesPerDay)
  if ((OrderDirection = 1) and (Hourof(time) = (PositionNumber * 2)) and (Hourof(time) > HourOpened) and (PositionNumber <= TradesPerDay)) then
  begin
    EntryPrice := Ask + (EntryDistance*Point);
    ProfitPrice := EntryPrice + (TakeProfit*Point);
    StopPrice := EntryPrice - ((StopLoss+Spread)*Point);
    //specifies if Buy or BuyStop should be used
    if (EntryDistance = 0) then
    begin
      SendInstantOrder(Symbol, op_Buy, BasePosition, StopPrice, ProfitPrice, '', PositionNumber, OrderHandle);
    end
    else
    begin
      SendPendingOrder(Symbol, op_BuyStop, BasePosition, StopPrice, ProfitPrice, EntryPrice, '', PositionNumber, OrderHandle);
    end;
    OrderDirection:= 0;
    HourOpened:= PositionNumber * 2;
    PositionNumber := PositionNumber +1;
  end;
  //resets trades to 0 for next day
  if (HourOf(time) = 23) then
  begin
    HourOpened:= 0;
    PositionNumber := 1;
  end;
end;

exports
  InitStrategy,
  DoneStrategy,
  ResetStrategy,
  GetSingleTick;
end.


To reverse the position direction change the variable OrderDirection at the start under var to 0.

Matt_mm
Posts: 17
Joined: Sat Jun 06, 2009 8:40 pm

#2 Postby Matt_mm » Sat Jul 04, 2009 11:18 pm

The problem was mine.

Due to spread in bid and ask a 100 tp and 100 stop are not actually 100 pips from the exit. Example:

A long position opened at 200 with 100 TP, 100 Stop:
Spread = 6
Open = Ask of 200
TP = 200 + 100 = 300 or a distance from the bid exit of 300+spread = 306
Stop = 200-100 = 100 or a distance from the bid exit of 300-spread = 106

To calculate an even probability after opening the position the distance to the exits needs to be offset:
TP = 100-Spread = 300
Stop = 100+Spread = 100

In this instance the probability over enough trades is 50% wins, 50% loss.


Return to “FT API”

Who is online

Users browsing this forum: No registered users and 18 guests