Forex Tester 2 Forum

Our site www.forextester.com
It is currently Thu Sep 18, 2014 4:39 am

All times are UTC - 5 hours




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Sat Jul 12, 2008 1:38 am 
Offline
Site Admin
User avatar

Joined: Sat Oct 21, 2006 4:39 pm
Posts: 838
Now it is time to place some orders, strategy should trade, right? :) Otherwise it is useless strategy.

There are 5 procedures that you can use to place, modify or delete orders.

SendInstantOrder - this procedure will instantly buy or sell by market price.

SendPendingOrder - this procedure will place pending order (Buy Limit, Buy Stop, Sell Limit, Sell Stop).

ModifyOrder - with this procedure you can modify existing order, change stop loss/take profit, or price for pending order.

CloseOrder - you can close opened position.

DeleteOrder - you can delete pending order.

Now we will modify our skeleton strategy from Lesson 1 (you can use this strategy as a template for your new strategies). Our new strategy will open a market order at 8 a.m. every day with TakeProfit = 50 and StopLoss = 100.

Let's save our project with different name (Save project as ...) DemoStrategy1. And change its description:

Code:
StrategyShortName('8 hour orders');
StrategyDescription('Strategy opens orders at 8 a.m.');


We will also need one external parameter - Currency, to define on which currency strategy should open orders:

Code:
var
  Currency: PChar;

...

RegOption('Currency', ot_Currency, Currency);


We will add following lines to GetSingleTick procedure. Here we receive all the price changes.

Code:
procedure GetSingleTick; stdcall;
var
  time: TDateTime;
  OrderHandle: integer;
begin
  if Symbol <> Currency then
    exit;

  time := iTime(Symbol, PERIOD_M1, 0);
  if (HourOf(time) = 8) and (OrdersTotal = 0) then
    SendInstantOrder(Symbol, op_Buy, 0.1, Ask - 100*Point, Ask + 50*Point, '', 0, OrderHandle);
end;


First that we do - check if it is our currency changes. Symbol is a function that returns name of current symbol (currency name) that was changed. If it is not our symbol we just exit from GetSingleTick and do nothing.

Then we obtain current time as a time of the last 1 minute bar for our currency and store it to the variable "time".

Then we check if current hour is 8 a.m. with HourOf(time) function (this function and other functions to work with time are located in DateTimeUtils module, and we added it to "uses" declaration) and if there are no other orders placed with OrdersTotal function.
If we meet both conditions, we open new position for buy with SendInstantOrder.

Complete code:
Code:
library DemoStrategy1;

uses
  SysUtils, DateUtils, StrategyInterfaceUnit, TechnicalFunctions;

var
  Currency: PChar;

procedure InitStrategy; stdcall;
begin
  StrategyShortName('8 hour orders');
  StrategyDescription('Strategy opens orders at 8 a.m.');

  RegOption('Currency', ot_Currency, Currency);
end;

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

procedure ResetStrategy; stdcall;
begin

end;

procedure GetSingleTick; stdcall;
var
  time: TDateTime;
  OrderHandle: integer;
begin
  if Symbol <> Currency then
    exit;

  time := iTime(Symbol, PERIOD_M1, 0);
  if (HourOf(time) = 8) and (OrdersTotal = 0) then
    SendInstantOrder(Symbol, op_Buy, 0.1, Ask - 100*Point, Ask + 50*Point, '', 0, OrderHandle);
end;

exports
  InitStrategy,
  DoneStrategy,
  ResetStrategy,
  GetSingleTick;

end.


Compile this code with Ctrl+F9, save it to Strategies folder and restart ForexTester.

If you are in Edit Mode now, then generate ticks and switch to Testing Mode.

Now open Strategies List, we can see the new strategy there named "8 hour orders". Check it and uncheck others, that only 1 strategy works at a time. Double click on it to open its parameters:

Image

Because we did not set initial currency in our code, it is empty. Double click on Currency parameter and select currency from list. Press "Apply" button.

Image

Now strategy is ready to work. Don't forget to enable all strategies with menu Testing -> Enable Strategy Execution. Press "Connect" button.

Image

Here we go! You can see that strategy opens orders at 8 a.m. with TakeProfit = 50 and StopLoss = 100.

_________________
Hasta la vista
Mike


Last edited by Terranin on Mon Jan 26, 2009 3:55 pm, edited 4 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 12, 2008 2:49 am 
Offline
Site Admin
User avatar

Joined: Sat Oct 21, 2006 4:39 pm
Posts: 838
A little bit more about parameters of SendInstantOrder:

Code:
SendInstantOrder(Symbol, op_Buy, 0.1, Ask - 100*Point, Ask + 50*Point, '', 0, OrderHandle);


it receives such parameters:

Symbol - currency name where to open position (we put Symbol function that returns our current currency 'GBPUSD')

OperationType - type of operation op_Buy or op_Sell

LotSize - lot size (0.1)

StopLoss - absolute stop loss level, we calculated it as Ask - 100*Point, where Ask is current Ask price (for sell it will be Bid price), Point is the minimum point value for this currency (0.0001)

TakeProfit - absolute take profit level, we calculated as Ask + 50*Point

Comment - you can place here your text comments for this order or leave it empty

MagicNumber - any value to separate one group of orders from another if necessary

If this function is successful it will return "true" value and OrderHandle value - unique order identificator that you can use later to modify, close or delete this order.


Now let's make our strategy fully configurable, so we can change lot size, stop loss/take profit level and open hour from parameters dialog:

Code:
library DemoStrategy1;

uses
  SysUtils, DateUtils, StrategyInterfaceUnit, TechnicalFunctions;

var
  Currency: PChar;
  OpenTime: integer= 8;
  StopLoss: integer = 100;
  TakeProfit: integer = 50;
  LotSize: double = 0.1;

procedure InitStrategy; stdcall;
begin
  StrategyShortName('8 hour orders');
  StrategyDescription('Strategy opens orders at 8 a.m.');

  RegOption('Currency', ot_Currency, Currency);
  RegOption('OpenTime', ot_Integer, OpenTime);
  RegOption('StopLoss', ot_Integer, StopLoss);
  RegOption('TakeProfit', ot_Integer, TakeProfit);
  RegOption('LotSize', ot_Double, LotSize);
  SetOptionDigits('LotSize', 1);
end;

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

procedure ResetStrategy; stdcall;
begin

end;

procedure GetSingleTick; stdcall;
var
  time: TDateTime;
  OrderHandle: integer;
begin
  if Symbol <> Currency then
    exit;

  time := iTime(Symbol, PERIOD_M1, 0);
  if (HourOf(time) = OpenTime) and (OrdersTotal = 0) then
    SendInstantOrder(Symbol, op_Buy, LotSize, Ask - StopLoss*Point, Ask + TakeProfit*Point, '', 0, OrderHandle);
end;

exports
  InitStrategy,
  DoneStrategy,
  ResetStrategy,
  GetSingleTick;

end.


Here we go:

Image

_________________
Hasta la vista
Mike


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 13, 2008 3:49 am 
Offline
Site Admin
User avatar

Joined: Sat Oct 21, 2006 4:39 pm
Posts: 838
SendPendingOrder procedure is very similar to SendInstantOrder, it uses one extra parameter - ExecutionPrice (where this order should be executed) and OrderType can be op_BuyLimit, op_BuyStop, op_SellLimit, op_SellStop.

SendPendingOrder('USDCAD', op_SellLimit, 0.2, 1.2200, 1.2100, 1.2150, '', 0, OrderHandle)

Let's modify our strategy to place pending order at 8 a.m. and if it was not executed until 10 a.m. we will delete it.

Code:
library DemoStrategy1;

uses
  SysUtils, DateUtils, StrategyInterfaceUnit, TechnicalFunctions;

var
  Currency: PChar;
  OrderHandle: integer;

procedure InitStrategy; stdcall;
begin
  StrategyShortName('8 hour orders');
  StrategyDescription('Strategy opens orders at 8 a.m.');

  RegOption('Currency', ot_Currency, Currency);
end;

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

procedure ResetStrategy; stdcall;
begin
  OrderHandle := -1;
end;

procedure GetSingleTick; stdcall;
var
  time: TDateTime;
  price: double;
begin
  if Symbol <> Currency then
    exit;

  time := iTime(Symbol, PERIOD_M1, 0);

  if (HourOf(time) = 8) and (OrdersTotal = 0) then
    begin
      price := Ask - 30*Point;
      SendPendingOrder(Symbol, op_BuyLimit, 0.1, price - 100*Point, price + 50*Point, price, '', 0, OrderHandle);
    end;

  // if we have an order
  if OrderHandle <> -1 then
    begin
      // select this order
      if not(OrderSelect(OrderHandle, SELECT_BY_TICKET, MODE_TRADES)) then
        begin
          OrderHandle := -1;
          exit;
        end;

      // check its type
      if OrderType <> tp_BuyLimit then
        begin
          OrderHandle := -1;
          exit;
        end;

      // if time is bigger then 10 a.m. ...
      if HourOf(time) >= 10 then
        begin
          DeleteOrder(OrderHandle);
          OrderHandle := -1;
        end;
    end;
end;

exports
  InitStrategy,
  DoneStrategy,
  ResetStrategy,
  GetSingleTick;

begin

end.


First of all this strategy is trying to pace a pending order for Buy Limit at 8 a.m. on 30 pips lower then current Ask price with 100/50 Stop Loss/Take Profit (note, that we moved OrderHandle variable from local procedure to global variable, it will keep our order id even when we exit GetSingleTick procedure. Also we reset this value in ResetStrategy procedure):

Code:
if (HourOf(time) = 8) and (OrdersTotal = 0) then
    begin
      price := Ask - 30*Point;
      SendPendingOrder(Symbol, op_BuyLimit, 0.1, price - 100*Point, price + 50*Point, price, '', 0, OrderHandle);
    end;


Image

Then strategy tracks our order with next code:

Code:
if OrderHandle <> -1 then ...


if our handle equals -1 then we do not have any order and do nothing

Code:
if not(OrderSelect(OrderHandle, SELECT_BY_TICKET, MODE_TRADES)) then
    begin
      OrderHandle := -1;
      exit;
    end;


with this code we select our order from orders' list (we will discuss this topic later, programmers who used MQL4 language will find this function identical to MQL4 OrderSelect function), if this function returns false then we assume that the order was closed by stop loss or take profit.

Code:
if OrderType <> tp_BuyLimit then
    begin
      OrderHandle := -1;
      exit;
    end;


Here we check our order type, because it could be already executed and changed its type to tp_Buy or tp_Sell. In this case it is not pending order any more.

Code:
if HourOf(time) >= 10 then
    begin
      DeleteOrder(OrderHandle);
      OrderHandle := -1;
    end;


And last check, if current time is equal or bigger than 10 a.m. and order was not executed we delete it.

Image

Image

_________________
Hasta la vista
Mike


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 11, 2010 4:48 am 
Offline

Joined: Sat Jul 10, 2010 11:41 am
Posts: 9
Hello - sorry for all the messages but I am determined to get ForexTester DLL's working in C++ :) Love the software.

I am now having problems compiling lesson #3 and not sure how to deal with cdecl errors (among others). Can you help?


Code:
#include <windows.h>
#include "StrategyInterfaceUnit.h"
#include "TechnicalFunctions.h"

// external parameters
char*   Currency;

EXPORT void __stdcall InitStrategy()
{
  StrategyShortName("8 hour orders");
  StrategyDescription("Strategy opens orders at 8 a.m.");

  RegOption("Currency", ot_Currency, &Currency);
}

EXPORT void __stdcall DoneStrategy()
{
  free(Currency);
}

EXPORT void __stdcall  ResetStrategy()
{

}

EXPORT void __stdcall GetSingleTick()
{
    TDateTime time;
    int OrderHandle;

  if (Symbol != Currency) then
    exit;

  time = iTime(Symbol, PERIOD_M1, 0);
  if ((HourOf(time) == 8) && (OrdersTotal == 0)) {
    SendInstantOrder(Symbol, op_Buy, 0.1, Ask - double(100)*Point, Ask + double(50)*Point, '', 0, OrderHandle);
  }
}


Code:
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(31) : error C2446: '!=' : no conversion from 'char *' to 'char *(__cdecl *)(void)'
        There is no context in which this conversion is possible
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(31) : error C2040: '!=' : 'char *(__cdecl *)(void)' differs in levels of indirection from 'char *'
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(32) : error C2065: 'then' : undeclared identifier
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(32) : error C2146: syntax error : missing ';' before identifier 'exit'
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(32) : warning C4551: function call missing argument list
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(34) : error C2664: 'iTime' : cannot convert parameter 1 from 'char *(__cdecl *)(void)' to 'char *'
        There is no context in which this conversion is possible
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(35) : error C3861: 'HourOf': identifier not found
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(36) : error C2297: '*' : illegal, right operand has type 'double (__cdecl *)(void)'
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(36) : error C2297: '*' : illegal, right operand has type 'double (__cdecl *)(void)'
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(36) : error C2137: empty character constant
c:\program files\forextester2\api\demostrategy1\demostrategy.cpp(36) : error C2664: 'SendInstantOrder' : cannot convert parameter 1 from 'char *(__cdecl *)(void)' to 'char *'
        There is no context in which this conversion is possible


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 11, 2010 5:44 am 
Offline

Joined: Sat Jul 10, 2010 11:41 am
Posts: 9
Hello again - I have read your response to other C++ questions and have decided to just switch to Delphi so that the examples will work. Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 12, 2013 4:03 am 
Offline

Joined: Fri Jul 12, 2013 3:47 am
Posts: 17
This thread looks quite old, but in case anyone is still interested, I've almost got the C++ version to work. However, the call to HourOf() is not available in C++.

To overcome this, I created a method-stub, to allow the dll to build, thus:

Code:
int HourOf(TDateTime dateTime)
{
     return 0;
}


Looking at the include-file, StrategyInterfaceUnit.h, TDateTime is #defined to double, but it's not clear what the format of this double is, when it's returned from iTime().

In order to implement HourOf in C/C++, we need to know this, so we can extract the hour from the time.

Can anyone help, please?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 12, 2013 10:54 am 
Offline

Joined: Mon Apr 01, 2013 3:55 am
Posts: 245
Hello,

Please read the last post of this tread: http://forextester.com/forum/viewtopic. ... ght=hourof

I hope it will help you.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 12, 2013 11:44 am 
Offline

Joined: Fri Jul 12, 2013 3:47 am
Posts: 17
Actually I managed to work it out after a bit more experimentation and I now have it working. However, thanks for your help.

Useful product, by the way. Well designed and works nicely.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 20, 2013 9:28 pm 
Offline

Joined: Sun Jan 02, 2011 6:05 pm
Posts: 103
amberwine wrote:
This thread looks quite old, but in case anyone is still interested, I've almost got the C++ version to work. However, the call to HourOf() is not available in C++.

To overcome this, I created a method-stub, to allow the dll to build, thus:

Code:
int HourOf(TDateTime dateTime)
{
return 0;
}


Looking at the include-file, StrategyInterfaceUnit.h, TDateTime is #defined to double, but it's not clear what the format of this double is, when it's returned from iTime().

In order to implement HourOf in C/C++, we need to know this, so we can extract the hour from the time.

Can anyone help, please?


Try this:

Code:
int HourOf(TDateTime dt)
{
  SYSTEMTIME st; 
  VariantTimeToSystemTime( dt, &st);       
  return st.wHour;
}



if the above code work, then you can look into the SYSTEMTIME structure
to cater for year, month, day, min...etc.

Translating MT4 code to Delphi is very painful work
I do direct FT2 function compatible to MT4 to reduce time and effort in porting, some of the functions for you to play around:



TimeSeconds()....TimeYear()

Others are:


#define datetime TDateTime

#define _double TIndexBuffer


//-- Copy all the clColor.. into new header and remove all the cl to same as
//-- MT colors
#define CLR_NONE cl_Transparent
#define color TColor


#define MathAbs(x) abs(x)

#define MathMin(x,y) min(x,y)
#define MathMax(x,y) max(x,y)
#define MathCeil(x) ceil(x)
#define MathFloor(x) floor(x)

#define MathMod(x, y) fmod( x, y)

double MathSqrt( double x)
{
return sqrt(x);
}


double MathPow(double x, double y)
{
return pow(x,y);
}

double MathRound(double number)
{
return (number >= 0) ? (int)(number + 0.5) : (int)(number - 0.5);
}

int StringFind( string s, string matched_text, int start=0)
{
return(s.find(matched_text,start));
}


int StringLen(PChar s)
{
return (strlen(s));
}
int StringLen( string s)
{
return (s.length());
}


int StrToInteger(PChar s)
{
return (atoi(s));
}


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 21, 2013 4:28 am 
Offline

Joined: Fri Jul 12, 2013 3:47 am
Posts: 17
Yes, I have had a go at porting a couple of MT4 indicators to FT2 (C++). I've had some success with converting the FXA0 indicator to FT2 (uses RSI and ATR internally), but I've found that the Calculate() function in FT2 seems to behave slightly differently to the start() method in MT4. However, I now have a working version in FT2 which actually looks quite promising.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group