Converting mql4 EA to mql5 - algorithmic-trading

I have been trying to figure out how to change my MQL4 code to MQL5. So far I've been able to change the RSI and MACD conditions and SendOrder() but there's a lot, like the ModifyOrder() and CloseOrder() amongst other stuff that I've not been able to do to complete it. I know this is a mouthful but I would really appreciate some help in completing this.
This is the original MQL4 code:
extern int MagicNumber=112223;
extern double Lots =0.005;
extern double StopLoss=0;
extern double TakeProfit=0;
extern int TrailingStop=0;
extern int Slippage=3;
int mode_main = 0;
int mode_signal = 1;
//+------------------------------------------------------------------+
// expert start function
//+------------------------------------------------------------------+
int start()
{
double MyPoint=_Point;
if(Digits==3 || Digits==5) MyPoint=Point*10;
double TheStopLoss=0;
double TheTakeProfit=0;
if( TotalOrdersCount()==0 )
{
int result=0;
if((iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_signal,0)<iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_main,0))&&(iRSI(NULL,PERIOD_M5,2,PRICE_CLOSE,0)>84)) // Here is your open buy rule
{
result=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,0,0,"EA",MagicNumber,0,Blue);
if(result>0)
{
TheStopLoss=0;
TheTakeProfit=0;
if(TakeProfit>0) TheTakeProfit=Ask+TakeProfit*MyPoint;
if(StopLoss>0) TheStopLoss=Ask-StopLoss*MyPoint;
OrderSelect(result,SELECT_BY_TICKET);
OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green);
}
return(0);
}
if((iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_main,0)<iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_signal,0))&&(iRSI(NULL,PERIOD_M5,2,PRICE_CLOSE,0)<16)) // Here is your open Sell rule
{
result=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,0,0,"EA",MagicNumber,0,Red);
if(result>0)
{
TheStopLoss=0;
TheTakeProfit=0;
if(TakeProfit>0) TheTakeProfit=Bid-TakeProfit*MyPoint;
if(StopLoss>0) TheStopLoss=Bid+StopLoss*MyPoint;
OrderSelect(result,SELECT_BY_TICKET);
OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green);
}
return(0);
}
}
for(int cnt=0;cnt<OrdersTotal();cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL &&
OrderSymbol()==Symbol() &&
OrderMagicNumber()==MagicNumber
)
{
if(OrderType()==OP_BUY)
{
if((iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_signal,0)>iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_main,0))&&(iRSI(NULL,PERIOD_M5,2,PRICE_OPEN,0)<16)) //here is your close buy rule
{
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage,Red);
}
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>MyPoint*TrailingStop)
{
if(OrderStopLoss()<Bid-MyPoint*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-TrailingStop*MyPoint,OrderTakeProfit(),0,Green);
return(0);
}
}
}
}
else
{
if((iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_main,0)>iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,mode_signal,0))&&(iRSI(NULL,PERIOD_M5,2,PRICE_OPEN,0)>84)) // here is your close sell rule
{
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage,Red);
}
if(TrailingStop>0)
{
if((OrderOpenPrice()-Ask)>(MyPoint*TrailingStop))
{
if((OrderStopLoss()>(Ask+MyPoint*TrailingStop)) || (OrderStopLoss()==0))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask+MyPoint*TrailingStop,OrderTakeProfit(),0,Red);
return(0);
}
}
}
}
}
}
return(0);
}
int TotalOrdersCount()
{
int result=0;
for(int i=0;i<OrdersTotal();i++)
{
OrderSelect(i,SELECT_BY_POS ,MODE_TRADES);
if (OrderMagicNumber()==MagicNumber) result++;
}
return (result);
}
Here is what I've done so far (MQL5):
#include <indicators/indicators.mqh>
CIndicators g_indicators;
CiRSI *g_rsi;
CiMACD *g_macd;
input int MagicNumber=112223;
input double Lots =0.005;
input double StopLoss=0;
input double TakeProfit=0;
input int TrailingStop=0;
input int Slippage=3;
int OnInit() {
g_rsi = new CiRSI();
g_indicators.Add(g_rsi);
g_macd = new CiMACD();
g_indicators.Add(g_macd);
bool is_init = g_rsi.Create(_Symbol, PERIOD_M5, 2, PRICE_CLOSE);
is_init &= g_macd.Create(_Symbol, PERIOD_M5, 12, 26, 9, PRICE_CLOSE);
return is_init ? INIT_SUCCEEDED : INIT_FAILED;
}
void OnTick() {
g_indicators.Refresh();
double MyPoint=_Point;
if(_Digits==3 || _Digits==5) MyPoint=_Point*10;
double TheStopLoss=0;
double TheTakeProfit=0;
if( TotalOrdersCount()==0 )
{
int result=0;
if (g_macd.Main(0) > g_macd.Signal(0) && g_rsi.Main(0) > 84) { // Here is your open Buy rule
Print("Signal!");
MqlTradeRequest request;
MqlTradeResult result;
MqlTradeCheckResult check;
ZeroMemory(request);
ZeroMemory(result);
ZeroMemory(check);
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); // Get the Ask Price
//--- parameters of request
request.action =TRADE_ACTION_PENDING; // type of trade operation
request.symbol =Symbol(); // symbol
request.volume =Lots; // volume of 0.005 lot
request.type =ORDER_TYPE_BUY; // order type
request.price = Ask; // price for opening
request.deviation=0; // allowed deviation from the price
request.magic =magicnumber; // MagicNumber of the order
request.tp = 0;
request.sl = 0;
request.type_filling=ORDER_FILLING_RETURN;
request.type_time=0;
request.expiration=0;
ObjectSetString(0,name,OBJPROP_TEXT,string(result.order));
if(!OrderSend(request,result))
{
Print(__FUNCTION__,": error ",GetLastError(),", retcode = ",result.retcode);
}
}
}
if (g_macd.Main(0) < g_macd.Signal(0) && g_rsi.Main(0) < 16) { // Here is your open Sell rule
Print("Signal!");
MqlTradeRequest request;
MqlTradeResult result;
MqlTradeCheckResult check;
ZeroMemory(request);
ZeroMemory(result);
ZeroMemory(check);
double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); // Get the Bid Price
//--- parameters of request
request.action =TRADE_ACTION_PENDING; // type of trade operation
request.symbol =Symbol(); // symbol
request.volume =Lots; // volume of 0.005 lot
request.type =ORDER_TYPE_SELL; // order type
request.price = Bid; // price for opening
request.deviation=0; // allowed deviation from the price
request.magic =magicnumber; // MagicNumber of the order
request.tp = 0;
request.sl = 0;
request.type_filling=ORDER_FILLING_RETURN;
request.type_time=0;
request.expiration=0;
ObjectSetString(0,name,OBJPROP_TEXT,string(result.order));
if(!OrderSend(request,result))
{
Print(__FUNCTION__,": error ",GetLastError(),", retcode = ",result.retcode);
}
}
}
}
}
Thanks in advance.

Yes, it may take long. luckily, someone wrote a library that you are welcome to download from https://www.mql5.com/ru/code/16006.
#include <MT4Orders.mqh> // if you have #include <Trade/Trade.mqh> in your MQL5 files, include this one AFTER.
int ticket = OrderSend(...);
same for `OrderModify()` and `OrderDelete` \ `OrderModify`
Keep in mind that this lib works for hedging mode only, so your MT5 must have a hedging mode.
full example below:
#include <MT45/MT4Orders.mqh>
//better to use MQL5 analogues of Ask etc for both MQL4 and MQL5, or redefine them
#define Ask SymbolInfoDouble(_Symbol,SYMBOL_ASK)
#define Bid SymbolInfoDouble(_Symbol,SYMBOL_BID)
#define Point _Point
#define Digits _Digits
// your inputs
extern int MagicNumber=112223;
extern double Lots =0.005;
extern double StopLoss=0;
extern double TakeProfit=0;
extern int TrailingStop=0;
extern int Slippage=3;
//int mode_main = 0; //probably throw this away
//int mode_signal = 1; //probably throw this away
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//initialize your indicators here
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//deinitialize your indicators here if you need to avoid memory leak
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
double MyPoint=_Point;
if(Digits==3 || Digits==5) MyPoint=Point*10;
double TheStopLoss=0;
double TheTakeProfit=0;
if( TotalOrdersCount()==0 )
{
TICKET_TYPE result=0;
if(isRule4Buy()) // Here is your open buy rule
{
result=OrderSend(Symbol(),OP_BUY,Lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),Slippage,0,0,"EA",MagicNumber,0,clrBlue);
if(result>0)
{
TheStopLoss=0;
TheTakeProfit=0;
if(TakeProfit>0) TheTakeProfit=Ask+TakeProfit*MyPoint;
if(StopLoss>0) TheStopLoss=Ask-StopLoss*MyPoint;
OrderSelect(result,SELECT_BY_TICKET);
OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green);
}
return;
}
if(isRule4Sell())
{
//simply copy the sell block
}
}
for(int cnt=0;cnt<OrdersTotal();cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL &&
OrderSymbol()==Symbol() &&
OrderMagicNumber()==MagicNumber
)
{
if(OrderType()==OP_BUY)
{
if(isRule4Sell())
{
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage,Red);
}
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>MyPoint*TrailingStop)
{
if(OrderStopLoss()<Bid-MyPoint*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-TrailingStop*MyPoint,OrderTakeProfit(),0,Green);
return;
}
}
}
}
else
{
//simply copy the sell block
}
}
}
}
//+------------------------------------------------------------------+
int TotalOrdersCount()
{
int result=0;
for(int i=0;i<OrdersTotal();i++)
{
OrderSelect(i,SELECT_BY_POS ,MODE_TRADES);
if (OrderMagicNumber()==MagicNumber) result++;
}
return (result);
}
//+------------------------------------------------------------------+
bool isRule4Buy()
{
#ifdef __MQL4__
return iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0)<iMACD(NULL,PERIOD_M5,12,26,9,PRICE_CLOSE,MODE_MAIN,0)
&& iRSI(NULL,PERIOD_M5,2,PRICE_CLOSE,0)>84;
#else
return true;
//replace with MT5
//g_macd.Main(0) > g_macd.Signal(0) && g_rsi.Main(0) > 84
#endif
}
bool isRule4Sell()
{
//similar for sell
return false;
}

Related

Can I send a stream from blob data in a database to PlaySound (MMSystem) rather than supplying a file name?

I need to be able to supply a stand alone system for a medical application that will be distributed free of charge to home users of blood pressure monitors, it is being designed to run off a memory stick and taken to doctors, pharmacists, hospitals, I would like to have a database file of spoken instructions for data entry fields for those who are not computer savvy.
The system is being developed to capture a large amount of observed symptomatic data from the user in the home which can then be taken to a doctor to open in the system and see the observation data as taken at the time for actual review and diagnosis, it is intended for those who are interested in helping themselves by letting their doctors or any other health practitioner understand by knowing what the patient experienced during the pain, feelings and other important information a doctor may rely on that they have identified.
At the moment I have
String file = frmMDI->dlg->InitialDir + "\\sounds\\" + "ObservationDateTimeField.wav";
speech->Send(file);
What this does is speak out the instruction for what is expected in the field when it has received the focus, it works fine as it is but would like to get the wav from the database so there is minimal files being distributed via usb.
in the OnEnter method, speech is a custom control that manages my needs, simply the PlaySound(...) requirement for .wav files, other controls work out how and when to send instruction.
Edit: a
add screen shot of observations window
Screen capture of main observation entry
I would like to have this as open source but I have no idea how to get it there, it is a development of ideas spanning 20 years, my code may be left wanting but it all works and has done so for a long time.
How do I go about it, if it can be done?
I have not had time to try too many things like sending a stream instead of a file, playsound works fine from a .wav sound file
Edit: Thanks to Spektre for time and code, very much appreciated.
PlaySound() cannot play audio from a stream. It can play from a file, a block of memory, or an EXE/DLL resource.
I would not recommend storing your WAV audio in database blobs. Use files or resources instead. But, if you must use a database, you can use the TDataSet::CreateBlobStream() method to get a read-only TStream to access the blob data, and then you can Read() that data into an allocated memory buffer, or CopyFrom() it into a TMemoryStream, and then you can have PlaySound() play from the memory of that buffer/stream.
If you really need to play streaming audio, you will have to use waveOutOpen()/waveOutPrepareHeader()/waveOutWrite() directly, or use more modern APIs like DirectSound or XAudio2 instead.
from my experience WAVEIN/WAVEOUT is the best sound api on win for this purpose... DirectSound is(was) buggy and very big latency so I stopped using it for good years ago...
Here my ancient C++ lib I originally wrote for my oscilloscope,spectral analyzator,signal generator apps but using it everywhere even in my ZXSpectrum emulator:
waveout.h:
//---------------------------------------------------------------------------
//--- WAVE IN/OUT class ver: 4.02 -------------------------------------------
//---------------------------------------------------------------------------
#ifndef _waveout_h
#define _waveout_h
//---------------------------------------------------------------------------
#include <mmsystem.h>
#include "fifo.h"
#include "lock.h"
//---------------------------------------------------------------------------
void CALLBACK wave_in_event(HWAVEIN hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
void CALLBACK wave_out_event(HWAVEOUT hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
//---------------------------------------------------------------------------
class wave_in
{
public:
bool _init,_fifo;
FIFO<BYTE> fifo;
WAVEHDR *hdr;
HWAVEIN hw;
WAVEFORMATEX buff_format;
DWORD buff_size;
DWORD freq; WORD chanels,bits,samples,buffers;
BYTE **buff;
int adr,num;
void CALLBACK (*event)(HWAVEIN hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
// void (*onreceive)(wave_in *wi,BYTE *data,int size);
void (__closure *onreceive)(wave_in *wi,BYTE *data,int size);
wave_in()
{
hdr=NULL;
buff=NULL;
buffers=0;
buff_size=0;
_init=false;
adr=0;
num=0;
event=wave_in_event;
onreceive=NULL;
}
~wave_in()
{
_free();
}
wave_in(wave_in& a) { *this=a; }
wave_in* operator = (const wave_in *a) { *this=*a; return this; }
//wave_in* operator = (const wave_in &a) { ...copy... return this; }
void _free()
{
adr=0;
num=0;
if (_init) { waveInClose(hw); _init=false; }
#ifdef _mmap_h
if (buff) for (int i=0;i<buffers;i++) if (buff[i]) mmap_del(buff[i]);
if (buff) mmap_del(buff);
if (hdr ) mmap_del(hdr );
#endif
if (buff)
{
for (int i=0;i<buffers;i++) if (buff[i]) delete[] buff[i];
delete[] buff;
buff=NULL;
}
if (hdr) { delete[] hdr; hdr=NULL; }
}
void init(DWORD _freq,WORD _chanels,WORD _bits,WORD _samples,WORD _buffers=5)
{
int i,ret;
_free();
buffers=_buffers;
if (buffers<1) buffers=1;
hdr=new WAVEHDR[buffers];
buff=new BYTE*[buffers];
#ifdef _mmap_h
if (hdr ) mmap_new(hdr ,buffers*sizeof(WAVEHDR));
if (buff) mmap_new(buff,buffers*sizeof(BYTE*));
#endif
freq =_freq;
chanels =_chanels;
bits =_bits;
samples =_samples;
buff_size=(chanels*bits*samples)>>3;
samples=(buff_size<<3)/(chanels*bits);
for (i=0;i<buffers;i++) buff[i]=new BYTE[buff_size];
#ifdef _mmap_h
for (i=0;i<buffers;i++) if (buff[i]) mmap_new(buff[i],buff_size);
#endif
buff_format.wFormatTag =WAVE_FORMAT_PCM; // set buffer format
buff_format.nChannels =chanels;
buff_format.nSamplesPerSec =freq;
buff_format.wBitsPerSample =bits;
buff_format.cbSize =0;
buff_format.nAvgBytesPerSec =(freq*chanels*bits)>>3;
buff_format.nBlockAlign =(chanels*bits)>>3;
if (event) ret=waveInOpen(&hw,WAVE_MAPPER,&buff_format,(DWORD_PTR)event,(DWORD_PTR)this,CALLBACK_FUNCTION);
else ret=waveInOpen(&hw,WAVE_MAPPER,&buff_format,0,0,CALLBACK_NULL);
if (ret!=MMSYSERR_NOERROR)
{
// waveInGetErrorText(ret,err,255);
return;
}
WAVEHDR hdr0;
hdr0.dwBufferLength=buff_size;
hdr0.dwUser=0;
hdr0.dwFlags=0;
hdr0.dwLoops=0;
hdr0.lpNext=NULL;
for (i=0;i<buffers;i++)
{
hdr[i]=hdr0;
hdr[i].lpData=buff[i];
}
_init=true;
}
void add()
{
if (!_init) return;
int i,ret;
BYTE *p;
p=buff[adr];
ret=waveInPrepareHeader(hw,&hdr[adr],sizeof(WAVEHDR));
if (ret!=MMSYSERR_NOERROR)
{
// waveInGetErrorText(ret,err,255);
return;
}
waveInAddBuffer(hw,&hdr[adr],sizeof(WAVEHDR));
if (ret!=MMSYSERR_NOERROR)
{
// waveInGetErrorText(ret,err,255);
return;
}
adr++;
if (adr>=buffers) adr=0;
num++;
}
void start()
{
if (!_init) return;
while (num<buffers) add();
waveInStart(hw);
}
void stop()
{
if (!_init) return;
waveInStop(hw);
}
};
//---------------------------------------------------------------------------
class wave_out:public multi_lock
{
public:
bool _init,_fifo;
FIFO<BYTE> fifo;
WAVEHDR *hdr;
HWAVEOUT hw;
WAVEFORMATEX buff_format;
DWORD buff_size;
DWORD freq; WORD chanels,bits,samples,buffers;
BYTE **buff;
int adr,num,err;
void CALLBACK (*event)(HWAVEOUT hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
wave_out()
{
hdr=NULL;
buff=NULL;
buffers=0;
buff_size=0;
_init=false;
adr=0;
num=0;
err=0;
event=wave_out_event;
}
~wave_out()
{
_free();
}
wave_out(wave_out& a) { *this=a; }
wave_out* operator = (const wave_out *a) { *this=*a; return this; }
//wave_out* operator = (const wave_out &a) { ...copy... return this; }
void _free()
{
adr=0;
num=0;
if (_init) { waveOutClose(hw); _init=false; }
#ifdef _mmap_h
if (buff) for (int i=0;i<buffers;i++) if (buff[i]) mmap_del(buff[i]);
if (buff) mmap_del(buff);
if (hdr ) mmap_del(hdr );
#endif
if (buff)
{
for (int i=0;i<buffers;i++) if (buff[i]) delete[] buff[i];
delete[] buff;
buff=NULL;
}
if (hdr) { delete[] hdr; hdr=NULL; }
}
void init(DWORD _freq,WORD _chanels,WORD _bits,WORD _samples,WORD _buffers=10)
{
int i,ret;
_free();
buffers=_buffers;
if (buffers<1) buffers=1;
hdr=new WAVEHDR[buffers];
buff=new BYTE*[buffers];
#ifdef _mmap_h
if (hdr ) mmap_new(hdr ,buffers*sizeof(WAVEHDR));
if (buff) mmap_new(buff,buffers*sizeof(BYTE*));
#endif
freq =_freq;
chanels =_chanels;
bits =_bits;
samples =_samples;
buff_size=(chanels*bits*samples)>>3;
samples=(buff_size<<3)/(chanels*bits);
for (i=0;i<buffers;i++) buff[i]=new BYTE[buff_size];
#ifdef _mmap_h
for (i=0;i<buffers;i++) if (buff[i]) mmap_new(buff[i],buff_size);
#endif
buff_format.wFormatTag =WAVE_FORMAT_PCM; // set buffer format
buff_format.nChannels =chanels;
buff_format.nSamplesPerSec =freq;
buff_format.wBitsPerSample =bits;
buff_format.cbSize =0;
buff_format.nAvgBytesPerSec =(freq*chanels*bits)>>3;
buff_format.nBlockAlign =(chanels*bits)>>3;
if (event) ret=waveOutOpen(&hw,WAVE_MAPPER,&buff_format,(DWORD_PTR)event,(DWORD_PTR)this,CALLBACK_FUNCTION);
else ret=waveOutOpen(&hw,WAVE_MAPPER,&buff_format,0,0,CALLBACK_NULL);
if (ret!=MMSYSERR_NOERROR)
{
// waveOutGetErrorText(ret,err,255);
return;
}
WAVEHDR hdr0;
hdr0.dwBufferLength=buff_size;
hdr0.dwUser=0;
hdr0.dwFlags=WHDR_INQUEUE;
hdr0.dwLoops=0;
hdr0.lpNext=NULL;
for (i=0;i<buffers;i++)
{
hdr[i]=hdr0;
hdr[i].lpData=buff[i];
}
_init=true;
}
void send(BYTE *data)
{
if (!_init) return;
lock();
if (num>buffers)
{
err++;
adr=0;
num=0;
}
DWORD i;
int ret;
BYTE *p;
p=buff[adr];
for (i=0;i<buff_size;i++) p[i]=data[i];
ret=waveOutPrepareHeader(hw,&hdr[adr],sizeof(WAVEHDR));
if (ret!=MMSYSERR_NOERROR)
{
// waveOutGetErrorText(ret,err,255);
unlock();
return;
}
waveOutWrite(hw,&hdr[adr],sizeof(WAVEHDR));
if (ret!=MMSYSERR_NOERROR)
{
// waveOutGetErrorText(ret,err,255);
unlock();
return;
}
adr++;
if (adr>=buffers) adr=0;
num++;
unlock();
}
void stop()
{
waveOutReset(hw);
}
};
//---------------------------------------------------------------------------
void CALLBACK wave_in_event(HWAVEIN hw,UINT msg,DWORD inst,DWORD p1,DWORD p2)
{
wave_in *w=(wave_in*)(void*)(DWORD_PTR)inst;
if (w==NULL) return;
if (msg==WIM_OPEN); // open wave HW
if (msg==WIM_DATA) // wave data send done
{
int adr0=w->adr-w->num;
while (adr0>=w->buffers) adr0-=w->buffers;
while (adr0< 0) adr0+=w->buffers;
if (w->onreceive) w->onreceive(w,w->buff[adr0],w->buff_size);
w->num--;
}
if (msg==WIM_CLOSE); // close wave HW
}
//---------------------------------------------------------------------------
void CALLBACK wave_out_event(HWAVEOUT hw,UINT msg,DWORD inst,DWORD p1,DWORD p2)
{
wave_out *w=(wave_out*)(void*)(DWORD_PTR)inst;
if (w==NULL) return;
w->lock();
if (msg==WOM_OPEN); // open wave HW
if (msg==WOM_DONE) w->num--; // wave data send done
if (msg==WOM_CLOSE); // close wave HW
w->unlock();
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
support file lock.h:
//---------------------------------------------------------------------------
//--- Multithread lock class ver 1.00 ---------------------------------------
//---------------------------------------------------------------------------
#ifndef _lock_h
#define _lock_h
//---------------------------------------------------------------------------
class single_lock
{
public:
CRITICAL_SECTION hnd;
single_lock() { InitializeCriticalSectionAndSpinCount(&hnd,0x00000400); }
~single_lock() { DeleteCriticalSection(&hnd); }
single_lock(single_lock& a) { *this=a; }
single_lock* operator = (const single_lock *a) { *this=*a; return this; }
// single_lock* operator = (const single_lock &a) { **** }
// thread safe functions
inline void lock() { EnterCriticalSection(&hnd); }
inline void unlock() { LeaveCriticalSection(&hnd); }
};
//---------------------------------------------------------------------------
const int _multi_lock_size=16; // max number of simultanious access
class multi_lock
{
public:
CRITICAL_SECTION hnd;
CRITICAL_SECTION dat[_multi_lock_size];
DWORD adr0,adr1,siz;
multi_lock() { InitializeCriticalSectionAndSpinCount(&hnd,0x00000400); for(int i=0;i<_multi_lock_size;i++) InitializeCriticalSectionAndSpinCount(&dat[i],0x00000400); adr0=0; adr1=0; siz=0; }
~multi_lock() { DeleteCriticalSection(&hnd); for(int i=0;i<_multi_lock_size;i++) DeleteCriticalSection(&dat[i]); }
multi_lock(multi_lock& a) { *this=a; }
multi_lock* operator = (const multi_lock *a) { *this=*a; return this; }
// multi_lock* operator = (const multi_lock &a) { **** }
// thread safe functions
inline void lock()
{
EnterCriticalSection(&hnd);
if (siz<_multi_lock_size)
{
siz++;
EnterCriticalSection(&dat[adr1]);
adr1++; if (adr1>=_multi_lock_size) adr1=0;
}
// else error();
LeaveCriticalSection(&hnd);
}
inline void unlock()
{
EnterCriticalSection(&hnd);
if (siz>0)
{
siz--;
LeaveCriticalSection(&dat[adr0]);
adr0++; if (adr0>=_multi_lock_size) adr0=0;
}
// else error();
LeaveCriticalSection(&hnd);
}
};
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
support file FIFO.h:
//---------------------------------------------------------------------------
//--- FIFO template class ver 2.08 ------------------------------------------
//---------------------------------------------------------------------------
#ifndef _fifo_h
#define _fifo_h
//---------------------------------------------------------------------------
//static bool _enable_fifo_debug=false;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
template <class T> class FIFO
{
public:
T *dat;
int adr0,adr1,size;
CRITICAL_SECTION lock;
FIFO() { dat=NULL; InitializeCriticalSectionAndSpinCount(&lock,0x00000400); alloc(16); }
~FIFO() { _free(); DeleteCriticalSection(&lock); }
FIFO(FIFO& a) { *this=a; }
FIFO* operator = (const FIFO *a){ *this=*a; return this; }
FIFO* operator = (const FIFO &a){ EnterCriticalSection(&a.lock); EnterCriticalSection(&lock); _alloc(a.size); adr0=a.adr0; adr1=a.adr1; for (int i=0;i<size;i++) dat[i]=a.dat[i]; LeaveCriticalSection(&lock); LeaveCriticalSection(&a.lock); return this; }
// already locked functions
inline int _adr_inc(int a) volatile { a++; if (a>=size) a=0; return a; }
inline int _adr_dec(int a) volatile { if (a!=adr0) a--; if (a<0) a=size-1; return a; }
inline void _alloc(int _size)volatile { if (dat) delete[] dat; dat=NULL; size=_size; adr0=0; adr1=0; dat=new T[size]; if (dat==NULL) size=0; _reset(); }
inline void _free() volatile { if (dat) delete[] dat; dat=NULL; size= 0; adr0=0; adr1=0; }
inline void _reset() volatile { adr0=0; adr1=0; }
inline void _in(T x) volatile { if (_is_full()) return; dat[adr1]=x; adr1=_adr_inc(adr1); }
inline T _out() volatile { if (_is_empty()){ T null; return null; } T x=dat[adr0]; adr0=_adr_inc(adr0); return x; }
inline T _peek_first() volatile { if (_is_empty()){ T null; return null; } T x=dat[adr0]; return x; }
inline T _peek_last() volatile { if (_is_empty()){ T null; return null; } int a=_adr_dec(adr1); T x=dat[a]; return x; }
inline bool _is_empty() volatile { bool ret=(adr0==adr1); return ret; }
inline bool _is_full() volatile { int a=_adr_inc(adr1); bool ret=(a==adr0); return ret; }
inline int _get_size() volatile { if (_is_empty()) return 0; if (_is_full()) return size; if (adr0<adr1) return adr1-adr0; else return size+adr1-adr0; }
// thread safe functions
void _lock() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); }
void _unlock() volatile { LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
void alloc(int _size) volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); _alloc(_size); LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
void reset() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); _reset(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
void in(T x) volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); _in(x); LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
T out() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); T x=_out(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
T peek_first() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); T x=_peek_first(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
T peek_last() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); T x=_peek_last(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
bool is_empty() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); bool x=_is_empty(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
bool is_full() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); bool x=_is_full(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
int get_size() volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); int x=_get_size(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
};
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
here simple usage (extracted from my generator hope I did not forget anything):
// globals and init
const int _size=20*1024;
wave_out wo;
WORD buffer[_size]; // your PCM sound data matching the init operands
wo.init(44100,2,16,_size,10); // sampling_freq,channels,bits,buffer size,buffers
// this in some timer or thread (fast enbough)
while (wo.num<4)
{
// here prepare buff[] data
wo.send((BYTE*)buff);
}
// force to stop on app exit or when needed
wo.stop();
The stuff was compiled on BDS2006 C++ Builder so in case you use newer compiler you might need to tweak some stuff...had not time will to port this to new compiler yet so if the case see this.
wave_out is for sound playback and wave_in is for recording both are using preferred windows sound device selected in control panel of Windows. To enable smooth playback just make sure that at least 4 buffers are filled in the sound que while (wo.num<4)... otherwise sound glitches might occur
You might also need to decode WAV files so here another ancient lib of mine RIFF.h:
//---------------------------------------------------------------------------
//--- RIFF WAVE format: 1.01 ------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _RIFF_h
#define _RIFF_h
//---------------------------------------------------------------------------
// 8bit PCM is unsigned
// 16bit PCM is signed 2'os complement little endian (big endian is RIFX)
//---------------------------------------------------------------------------
struct _wave_chunk
{
DWORD ids;
DWORD len;
_wave_chunk(){ ids=' '; len=0; }
_wave_chunk(_wave_chunk& a){ *this=a; }; ~_wave_chunk(){}; _wave_chunk* operator = (const _wave_chunk *a) { *this=*a; return this; }; /*_wave_chunk* operator = (const _wave_chunk &a) { ...copy... return this; };*/
};
struct _wave_hdr
{
DWORD ids; // "RIFF"
DWORD len;
DWORD tps; // "WAVE"
_wave_hdr(){ ids='FFIR'; len=0; tps='EVAW'; }
_wave_hdr(_wave_hdr& a){ *this=a; }; ~_wave_hdr(){}; _wave_hdr* operator = (const _wave_hdr *a) { *this=*a; return this; }; /*_wave_hdr* operator = (const _wave_hdr &a) { ...copy... return this; };*/
};
struct _wave_fmt
{
DWORD ids; // "fmt "
DWORD len; // 16,18,40
WORD format; // 1 = PCM linear quantization
/* 0x0001 WAVE_FORMAT_PCM PCM
0x0003 WAVE_FORMAT_IEEE_FLOAT IEEE float
0x0006 WAVE_FORMAT_ALAW 8-bit ITU-T G.711 A-law
0x0007 WAVE_FORMAT_MULAW 8-bit ITU-T G.711 ยต-law
0xFFFE WAVE_FORMAT_EXTENSIBLE Determined by SubFormat */
WORD chanels;
DWORD samplerate;
DWORD byterate;
WORD blockalign;
WORD bits;
WORD ext_len; // extension length 0,22
WORD ext_validbits;
DWORD ext_channelmask;
BYTE ext_subformat[16];
_wave_fmt(){ ids=' tmf'; len=16; format=1; chanels=1; samplerate=44100; bits=8; ext_len=0; ext_validbits=0; ext_channelmask=0; for (int i=0;i<16;i++) ext_subformat[i]=0; compute(); }
_wave_fmt(_wave_fmt& a){ *this=a; }; ~_wave_fmt(){}; _wave_fmt* operator = (const _wave_fmt *a) { *this=*a; return this; }; /*_wave_fmt* operator = (const _wave_fmt &a) { ...copy... return this; };*/
void compute()
{
byterate=(chanels*samplerate*bits)/8;
blockalign=(chanels*bits)/8;
}
};
struct _wave_dat
{
DWORD ids; // "data"
DWORD len;
_wave_dat(){ ids='atad'; len=0; }
_wave_dat(_wave_dat& a){ *this=a; }; ~_wave_dat(){}; _wave_dat* operator = (const _wave_dat *a) { *this=*a; return this; }; /*_wave_dat* operator = (const _wave_dat &a) { ...copy... return this; };*/
};
//---------------------------------------------------------------------------
class wave
{
public:
AnsiString name;
int hnd;
bool readonly;
_wave_hdr hdr;
_wave_fmt fmt;
_wave_dat dat;
wave();
~wave();
void create(AnsiString _name);
void write(BYTE *data,DWORD size);
bool open(AnsiString _name);
DWORD read(BYTE *data,DWORD size);
void close();
};
//---------------------------------------------------------------------------
wave::wave()
{
name=0;
hnd=-1;
readonly=true;
}
//---------------------------------------------------------------------------
wave::~wave()
{
close();
}
//---------------------------------------------------------------------------
void wave::create(AnsiString _name)
{
close();
readonly=true;
// hdr=_wave_hdr();
// fmt=_wave_fmt();
// dat=_wave_dat();
hdr.len=sizeof(hdr)-8;
dat.len=0;
fmt.compute();
name=_name;
hnd=FileCreate(name);
if (hnd<0) return;
FileWrite(hnd,&hdr,sizeof(hdr));
FileWrite(hnd,&fmt,fmt.len+8);
FileWrite(hnd,&dat,sizeof(dat));
readonly=false;
}
//---------------------------------------------------------------------------
bool wave::open(AnsiString _name)
{
close();
readonly=true;
name=_name;
hnd=FileOpen(name,fmOpenRead);
if (hnd<0) return false;
if (FileRead(hnd,&hdr,sizeof(hdr))<sizeof(hdr)){ close(); return false; }
if (hdr.ids!='FFIR') return false;
if (hdr.tps!='EVAW') return false;
_wave_chunk chk;
DWORD sz=sizeof(chk),l;
for(;;)
{
if (FileRead(hnd,&chk,sz)<sz){ close(); return false; }
if (chk.ids==' tmf')
{
fmt.ids=chk.ids;
fmt.len=chk.len;
if (FileRead(hnd,((BYTE*)&fmt)+sz,chk.len)<chk.len){ close(); return false; }
}
else if (chk.ids=='atad')
{
dat.ids=chk.ids;
dat.len=chk.len;
return true;
}
else FileSeek(hnd,int(chk.len),1);
}
}
//---------------------------------------------------------------------------
void wave::write(BYTE *data,DWORD size)
{
if (hnd<0) return;
hdr.len+=size;
dat.len+=size;
if (!readonly) FileWrite(hnd,data,size);
}
//---------------------------------------------------------------------------
DWORD wave::read(BYTE *data,DWORD size)
{
if (hnd<0) return 0;
return FileRead(hnd,data,size);
}
//---------------------------------------------------------------------------
void wave::close()
{
name="";
if (hnd<0) return;
FileSeek(hnd,0,0);
if (!readonly) FileWrite(hnd,&hdr,sizeof(hdr));
FileClose(hnd);
hnd=-1;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
And usage:
// globals
wave wav;
wave_out wo;
BYTE *buff;
// init
wav.open("tetris2.wav"); // any file ...
wo.init(wav.fmt.samplerate,wav.fmt.chanels,wav.fmt.bits,dt*wav.fmt.samplerate/1000,10);
buff=new BYTE[wo.buff_size];
// timer 20ms ...
while (wo.num<4)
{
wav.read(buff,wo.buff_size);
wo.send(buff);
}
// exit
wo.stop();
wav.close();
delete[] buff;
the wav.read(...) returns number of BYTEs read so once it hit less than buffer size or even equals to zero it means you already on end of wavefile ... Now as you will have the wav in memory just rewrite the file access to memory access ...

g++ optimizes out nullpointer checks

I have a function that is working if I compile with O0 flag but crashes on a function called on a nullptr if compiled with O2.
If I add some macros to disable optimizations around that function it will work properly.
https://i.imgur.com/ObYiiEl.png
if (LPPARTY pkParty = GetParty())
{
struct FPartyBuff
{
const CSkillProto* pkSk;
DWORD casterPID;
int iAmount1, iDur1;
int iAmount2, iDur2;
FPartyBuff(const CSkillProto* pkSkill, DWORD caster, int amount1, int dur1, int amount2, int dur2)
: pkSk(pkSkill), casterPID(caster), iAmount1(amount1), iDur1(dur1), iAmount2(amount2), iDur2(dur2) {}
void operator() (LPCHARACTER ch)
{
bool bOverride = true;
if (ch && ch->GetPlayerID() != casterPID)
{
if (pkSk->bPointOn != POINT_NONE)
{
ch->AddAffect(pkSk->dwVnum, pkSk->bPointOn, iAmount1, pkSk->dwAffectFlag, iDur1, 0, bOverride, false, casterPID);
bOverride = false;
}
if (pkSk->bPointOn2 != POINT_NONE)
{
ch->AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag, iDur2, 0, bOverride, false, casterPID);
bOverride = false;
}
}
}
};
if (pkVictim && pkParty->IsMember(pkVictim->GetPlayerID()))
{
FPartyBuff f(pkSk, GetPlayerID(), iAmount, iDur, iAmount2, iDur2);
pkParty->ForEachNearMember(f);
}
}
But without them this part of the code calls IsMember on pkParty even when it is a nullpointer.
LPPARTY is defined as CParty*
Why is it happening?

Mql5 function for selecting open orders by Ticket, then Symbol, and trade Direction

Total newbie to Mql5, and need some help with this int OpenOrders() piece of code originally from Mql4 EA's, that finds open positions - (if any), and selects originally by SYMBOL, and MAGIC Number, and the expert doesn't open any other positions for as long as a trade it has opened on that symbol has not yet been closed.
I wish the EA to identify a TICKET it has opened, related SYMBOL, and POSITION_TYPE to be used in the ONTICK, and not open any other trades on the same chart until that one position is closed, but can continue trading on any other charts.
input double LotSize =0.3;
input double Incriment =0.01;
input int StopLoss =50;
input int TakeProfit =100;
input int Trend =21;
input int Momentum =21;
input int Strength =13;
int adxlevel =34;
int buylevel =62;
int selllevel =36;
//---------------------
double pips;
#include <Trade\Trade.mqh>
CTrade Execute;
ulong passport, StopLevel;
double ask, bid;
double takeout=0,stopout=0;
int moving,rsi,adx,Spread;
//+------------------------------------------------------------------+
int OnInit()
{
//---
double ticksize = SymbolInfoDouble(_Symbol,SYMBOL_POINT);
if(_Digits==3||_Digits==4)
pips=ticksize*1000;
else
pips =ticksize;
//---
moving=iMA(_Symbol,PERIOD_CURRENT,Trend,0,MODE_SMA,PRICE_CLOSE);
rsi=iRSI(_Symbol,PERIOD_CURRENT,Momentum,PRICE_MEDIAN);
adx=iADX(_Symbol,PERIOD_CURRENT,Strength);
//---
return(INIT_SUCCEEDED);
}
***int OpenOrders()
{
int BUYS=0,SELLS=0;
for(int i=0; i<PositionsTotal(); i++)
{
if(PositionSelectByTicket(passport)==false) break;
int dealtype=(int)PositionGetInteger(POSITION_TYPE); // buy or sell
// string position_symbol=PositionGetString(POSITION_SYMBOL); // chart symbol
if(Symbol()==PositionGetSymbol(i) && passport==PositionGetTicket(POSITION_TICKET))
{
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) BUYS++;
if(PositionGetInteger(POSITION_TYPE)==ORDER_TYPE_SELL) SELLS++;
}
}
//---
if(BUYS>0) return(BUYS);
else return(SELLS);
}***
//+------------------------------------------------------------------+
void OnTick()
{
//---
MqlRates rates[3];
double movingarray[],rsiarray[],adxarray[];
CopyRates(_Symbol,PERIOD_CURRENT,1,3,rates);
CopyBuffer(rsi,0,1,3,rsiarray);
CopyBuffer(adx,0,1,3,adxarray);
ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
Spread=int(SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));
StopLevel=SymbolInfoInteger(Symbol(),SYMBOL_TRADE_STOPS_LEVEL);
//---
if(OpenOrders()==0)
{
if(rates[0].open > moving )// CONDITION
if(rsiarray[0] > buylevel && rsiarray[1] < buylevel )//SIGNAL
{
if(TakeProfit>0) takeout=ask+TakeProfit*pips;
if(StopLoss>0) stopout=ask-StopLoss*pips;
Execute.Buy(LotSize,NULL,ask,stopout,takeout,NULL);
passport=Execute.ResultOrder();
Print("BUY Opened");
}
if(rates[0].open < moving )//CONTITION
if(rsiarray[0] < selllevel &&rsiarray[1] > selllevel )//SIGNAL
{
if(TakeProfit>0) takeout=bid+TakeProfit*pips;
if(StopLoss>0) stopout=bid-StopLoss*pips;
Execute.Sell(LotSize,NULL,bid,stopout,takeout,NULL);
passport=Execute.ResultOrder();
Print("SELL Opened");
}
}
//---
if(OpenOrders()>0)
{
int dealtype=(int)PositionGetInteger(POSITION_TYPE);
if(dealtype==POSITION_TYPE_BUY)
if(rsiarray[0] < buylevel )
{
Execute.PositionClose(passport);
passport=0;
}
else if(dealtype==POSITION_TYPE_SELL)
if(rsiarray[0] > selllevel )
{
Execute.PositionClose(passport);
passport=0;
}
}
}
I think what you really after is this:
input double LotSize =0.3;
input double Incriment =0.01;
input int StopLoss =50;
input int TakeProfit =100;
input int Trend =21;
input int Momentum =21;
input int Strength =13;
int adxlevel =34;
int buylevel =62;
int selllevel =36;
//---------------------
double pips;
#include <Trade\Trade.mqh>
CTrade Execute;
ulong StopLevel;
double ask, bid;
double takeout=0,stopout=0;
int moving,rsi,adx,Spread;
//+------------------------------------------------------------------+
int OnInit()
{
//---
double ticksize = SymbolInfoDouble(_Symbol,SYMBOL_POINT);
if(_Digits==3||_Digits==4)
pips=ticksize*1000;
else
pips =ticksize;
//---
moving=iMA(_Symbol,PERIOD_CURRENT,Trend,0,MODE_SMA,PRICE_CLOSE);
rsi=iRSI(_Symbol,PERIOD_CURRENT,Momentum,PRICE_MEDIAN);
adx=iADX(_Symbol,PERIOD_CURRENT,Strength);
//---
Execute.SetExpertMagicNumber(0xCAFE); // INCLUDED
Execute.SetAsyncMode(false); // CHANGED
return(INIT_SUCCEEDED);
}
int OpenPositions(ulong &passport)
{
int BUYS=0,SELLS=0;
for(int i=0; i<PositionsTotal(); i++)
{
ulong ticket=PositionGetTicket(i); // changed
if(PositionSelectByTicket(ticket)==false) break;
int dealtype=(int)PositionGetInteger(POSITION_TYPE); // buy or sell
// string position_symbol=PositionGetString(POSITION_SYMBOL); // chart symbol
if(Symbol()==PositionGetSymbol(i) && 0xCAFE==PositionGetInteger(POSITION_MAGIC)) // CHANGED
{
passport = ticket; // CHANGED
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) BUYS++;
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) SELLS++; // CHANGED
}
}
//---
if(BUYS>0) return(BUYS);
else return(SELLS);
}
//+------------------------------------------------------------------+
void OnTick()
{
//---
MqlRates rates[3];
double movingarray[],rsiarray[],adxarray[];
CopyRates(_Symbol,PERIOD_CURRENT,1,3,rates);
CopyBuffer(rsi,0,1,3,rsiarray);
CopyBuffer(adx,0,1,3,adxarray);
ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
Spread=int(SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));
StopLevel=SymbolInfoInteger(Symbol(),SYMBOL_TRADE_STOPS_LEVEL);
//---
ulong passport = 0; // CHANGED
int positions = OpenPositions(passport); // CHANGED
if(positions==0) // CHANGED
{
if(rates[0].open > moving )// CONDITION
if(rsiarray[0] > buylevel && rsiarray[1] < buylevel )//SIGNAL
{
if(TakeProfit>0) takeout=ask+TakeProfit*pips;
if(StopLoss>0) stopout=ask-StopLoss*pips;
Execute.Buy(LotSize,NULL,ask,stopout,takeout,NULL);
Print("BUY Opened");
}
if(rates[0].open < moving )//CONTITION
if(rsiarray[0] < selllevel &&rsiarray[1] > selllevel )//SIGNAL
{
if(TakeProfit>0) takeout=bid+TakeProfit*pips;
if(StopLoss>0) stopout=bid-StopLoss*pips;
Execute.Sell(LotSize,NULL,bid,stopout,takeout,NULL);
passport=Execute.ResultDeal(); // CHANGED
Print("SELL Opened");
}
}
else if(positions>0) // CHANGED to prevent on the same tick do both
{
int dealtype=(int)PositionGetInteger(POSITION_TYPE);
if(dealtype==POSITION_TYPE_BUY)
if(rsiarray[0] < buylevel )
{
Execute.PositionClose(passport);
}
else if(dealtype==POSITION_TYPE_SELL)
if(rsiarray[0] > selllevel )
{
Execute.PositionClose(passport);
}
}
}
I dont tested the changes. And it should be fine most part of time. It will only have problems when having delay to execute the Buy/Sell stuff.

Forward conditioned slicing with Frama-C

From the post Understanding Frama-C slicer results, it seems Frama-C supports the forward conditioned slicing with Frama-C. For the following example test.c, I wonder how to do the forward conditioned slicing with the specific function "event". #Pascal Cuoq
/*# requires a == 1 ;
*/
#include <stdio.h>
int event() {
int r;
scanf("%d", &r);
if (r>10) return 1;
else return 0;
}
void event_process() {
int x=0;
printf("event process\n");
x=1;
}
void no_event()
{
int y=0;
printf("no event\n");
}
void main ( ) {
int a;
if((a=event()) == 1)
event_process();
else
no_event();
printf("in main\n");
return;
}
I tried frama-c test.c -slice-calls event -then-on 'Slicing export' -print, why it outputs as follows:
/* Generated by Frama-C */
void event_slice_1(void)
{
return;
}
void main(void)
{
event_slice_1();
return;
}

Does Mac OS X have pthread_spinlock_t type?

I didn't find it in Mac, but almost all Linux os support it..
Any one knows how to port it to mac?
Here is drop in replacement code. You should be able to put this in a header file and drop it in your project.
typedef int pthread_spinlock_t;
int pthread_spin_init(pthread_spinlock_t *lock, int pshared) {
__asm__ __volatile__ ("" ::: "memory");
*lock = 0;
return 0;
}
int pthread_spin_destroy(pthread_spinlock_t *lock) {
return 0;
}
int pthread_spin_lock(pthread_spinlock_t *lock) {
while (1) {
int i;
for (i=0; i < 10000; i++) {
if (__sync_bool_compare_and_swap(lock, 0, 1)) {
return 0;
}
}
sched_yield();
}
}
int pthread_spin_trylock(pthread_spinlock_t *lock) {
if (__sync_bool_compare_and_swap(lock, 0, 1)) {
return 0;
}
return EBUSY;
}
int pthread_spin_unlock(pthread_spinlock_t *lock) {
__asm__ __volatile__ ("" ::: "memory");
*lock = 0;
return 0;
}
See discussion, and Github source
EDIT: Here's a class that works on all OSes that includes a workaround for missing pthread spinlocks on OSX:
class Spinlock
{
private: //private copy-ctor and assignment operator ensure the lock never gets copied, which might cause issues.
Spinlock operator=(const Spinlock & asdf);
Spinlock(const Spinlock & asdf);
#ifdef __APPLE__
OSSpinLock m_lock;
public:
Spinlock()
: m_lock(0)
{}
void lock() {
OSSpinLockLock(&m_lock);
}
bool try_lock() {
return OSSpinLockTry(&m_lock);
}
void unlock() {
OSSpinLockUnlock(&m_lock);
}
#else
pthread_spinlock_t m_lock;
public:
Spinlock() {
pthread_spin_init(&m_lock, 0);
}
void lock() {
pthread_spin_lock(&m_lock);
}
bool try_lock() {
int ret = pthread_spin_trylock(&m_lock);
return ret != 16; //EBUSY == 16, lock is already taken
}
void unlock() {
pthread_spin_unlock(&m_lock);
}
~Spinlock() {
pthread_spin_destroy(&m_lock);
}
#endif
};
Try using OSSpinLock instead. Documentation is here: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/spinlock.3.html
If the performance of your lock is not critical, pthread_mutex_t can be used as a drop replacement for pthread_spinlock_t, which makes porting easy.
I have used instead (that is natively supported by OS X intel)
pthread_rwlock_t lock;
pthread_rwlock_init
pthread_rwlock_wrlock
pthread_rwlock_unlock
And that works very fine as well

Resources