## Lesson 3 - Working with orders

Examples step by step how to make your own automated strategy or user indicator
Message
Author
Terranin
Posts: 833
Joined: Sat Oct 21, 2006 4:39 pm

### Lesson 3 - Working with orders

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: Select all

`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: Select all

`var  Currency: PChar;...RegOption('Currency', ot_Currency, Currency);`

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

Code: Select all

`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: Select all

`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;beginend;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:

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.

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

Here we go! You can see that strategy opens orders at 8 a.m. with TakeProfit = 50 and StopLoss = 100.
Last edited by Terranin on Mon Jan 26, 2009 3:55 pm, edited 4 times in total.
Hasta la vista
Mike

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

Code: Select all

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

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: Select all

`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;beginend;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:

Hasta la vista

Mike

Terranin
Posts: 833
Joined: Sat Oct 21, 2006 4:39 pm
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: Select all

`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;beginend.`

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: Select all

`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;`

Then strategy tracks our order with next code:

Code: Select all

`if OrderHandle <> -1 then ...`

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

Code: Select all

`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: Select all

`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: Select all

`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.

Hasta la vista

Mike

etw
Posts: 9
Joined: Sat Jul 10, 2010 11:41 am
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: Select all

`#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: Select all

`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 possiblec:\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 identifierc:\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 listc:\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 possiblec:\program files\forextester2\api\demostrategy1\demostrategy.cpp(35) : error C3861: 'HourOf': identifier not foundc:\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 constantc:\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`

etw
Posts: 9
Joined: Sat Jul 10, 2010 11:41 am
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!

amberwine
Posts: 17
Joined: Fri Jul 12, 2013 3:47 am
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: Select all

`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.

FX Helper
Posts: 1045
Joined: Mon Apr 01, 2013 3:55 am
Hello,

amberwine
Posts: 17
Joined: Fri Jul 12, 2013 3:47 am
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.

KelvinHand
Posts: 103
Joined: Sun Jan 02, 2011 6:05 pm
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.

Try this:

Code: Select all

`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));
}

amberwine
Posts: 17
Joined: Fri Jul 12, 2013 3:47 am
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.

alpente
Posts: 4
Joined: Wed Dec 23, 2015 9:37 pm

### Re: Lesson 3 - Working with orders

Although this thread is very old, no one has posted a solution.
I hope this can help.

Lesson 3 - Working with orders (VisualC++ Version)

Code: Select all

`#include <windows.h>#include "StrategyInterfaceUnit.h"#include "TechnicalFunctions.h"#include "ATLComTime.h"      // needed 'cause of COleDateTime in function HourOf// prototypesint HourOf(TDateTime time);// esternal parametersPChar Currency = "EURUSD";EXPORT void __stdcall InitStrategy(){   StrategyShortName("8 hour orders");   StrategyDescription("Strategy opens orders at 8 a.m. c");   RegOption("Currency", ot_Currency, &Currency);}EXPORT void __stdcall DoneStrategy(){   free(Currency);}EXPORT void __stdcall  ResetStrategy(){}EXPORT void __stdcall GetSingleTick(){   TDateTime time;   int OrderHandle;      char* s = Symbol();    if(strcmp(Symbol(), Currency) != 0) { return; }      time = iTime(Symbol(), PERIOD_M1, 0);   // COleDateTime t = COleDateTime((DATE)time);   // if(t.GetHour() == 8 && OrdersTotal() == 0)   if(HourOf(time) == 8 && OrdersTotal() == 0)   {      SendInstantOrder(Symbol(), op_Buy, 0.1, Ask()-100*Point(), Ask() + 50*Point(), "", 0, OrderHandle);   }}int HourOf(TDateTime time) // TDateTime is the same as double{   COleDateTime t = COleDateTime((DATE)time);   int hour = t.GetHour();   return hour;}`

HourOf is a Delphi function (*1).
The type of input of the HourOf function is TDateTime that really is a double type value (*2).
In VisualC++ is there the type COleDateTime that stores date and time the same way TDateTime does (*2)(*3)(*4).
The function COleDateTime::GetHour is the VisualC++ equivalent for HourOf (*5).

Code: Select all

`// This is the function that does the jobint HourOf(TDateTime time) // TDateTime is the same as double{    COleDateTime t = COleDateTime((DATE)time);    int hour = t.GetHour()    return hour;}`

Bibliography