Why does this EA (in early development) not produce an alert, or an error? - mql4

#property strict
string subfolder = "ipc\\";
int last_read = 0;
int t = 0;
struct trade_message
{
int time; // time
string asset; // asset
string direction; // direction
double open_price; // open
double stop_price; // open
double close_price;// open
float fraction; // fraction
string comment; // comment
string status; // status
};
trade_message messages[];
int OnInit()
{
int FH = FileOpen(subfolder+"processedtime.log",FILE_BIN);
if(FH >=0)
{
last_read = FileReadInteger(FH,4);
FileClose(FH);
}
return(INIT_SUCCEEDED);
}
void OnTick()
{
int FH=FileOpen(subfolder+"data.csv",FILE_READ|FILE_CSV, ","); //open file
int p=0;
while(!FileIsEnding(FH))
{
t = StringToInteger(FileReadString(FH));
if(t<=last_read)
{
break;
}
do
{
messages[p].time = t; // time
messages[p].direction = FileReadString(FH); // direction
messages[p].open_price = StringToDouble(FileReadString(FH)); // open
messages[p].stop_price = StringToDouble(FileReadString(FH)); // stop
messages[p].close_price = StringToDouble(FileReadString(FH)); // close
messages[p].fraction = StringToDouble(FileReadString(FH)); // fraction (?float)
messages[p].comment = FileReadString(FH); // comment
messages[p].status = FileReadString(FH); // status
Alert(messages[p].comment);
}
while(!FileIsLineEnding(FH));
p++;
Alert("P = ",p,"; Array length = ", ArraySize(messages));
}
FileClose(FH);
last_read = t;
FileDelete(subfolder+"processedtime.log");
FH = FileOpen(subfolder+"processedtime.log",FILE_BIN);
FileWriteInteger(FH,t,4);
FileClose(FH);
ArrayFree(messages);
}
The code is in tick function in order to test it before taking it out to a function.
The data.csv file is:
Timestamp
Asset
Direction
Price
Stop
Profit
Fraction
Comment
Status
xxx
yyy
SHORT
13240
13240
13220
0.5
yyy SHORT 13240 - taken half at 13220 and stop to breakeven
U
xxx
yyy
SHORT
13240
13262
13040
1.0
55%
DP
The processedtime.log is not being created.

So 2 problems, both of my own making.
Not skipping the header row, simply remedied by inserting
do f = FileReadString(FH);
while(!FileIsLineEnding(FH));
after FileOpen() (easier than altering my source for data.csv), and
forgetting about the asset part of my structure, thus ensuring my structures got out of sync with my lines!! Remedied by adding messages[p].asset = FileReadString(FH); between messages[p].time = t and messages[p].direction = FileReadString(FH);

Related

EA Opens more orders than expected in MQL4

Everything seems fine. But EA usually opens multiple trades in the same second... The way I built it is very linear and i can't seem to spot the logical mistake. It is basically a random martingale EA to test stuff out. Any indicator (that's why I called it random, haven't decided myself) can be put in there.
Basic idea is that it has an upper and lower threshold which determines when it is in buy zone and when at sell zone. Once it is in either zone, if trend goes against it (determined by indicator's value, not symbol's price) it opens another trade with the same SL/TP of the initial order. Also it checks whether initial trade still runs so it does not open other ones and once the initial trade is open. After that the criterias about the rest of the trades (that go against the trade are different).
The problem is that it opens multiple trades at times that it shouldn't, or like 3-4 trades within the same second or two. Any idea why this happens?
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
input int stepValue = 5;
input double lotsize = 0.01;
input int stoploss = 2000;
input int takeprofit = 140;
input int slippage = 10;
input double upper_border = 60.0;
input double lower_border = 40.0;
const string EAComment = "Xind";
string mode = "";
bool first_trade = false;
int InitTicket = 1;
double X = 0.0;
double X_Last = 0.0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
first_trade = false;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
SearchSignal();
if (mode == "Buy")
{
if (first_trade == false)
{
Buy();
}
if (first_trade == true)
{
MartinCheck();
CloseCheck();
}
}
if (mode == "Sell")
{
if (first_trade == false)
{
Sell();
}
if (first_trade == true)
{
MartinCheck();
CloseCheck();
}
}
}
//+------------------------------------------------------------------+
void Buy()
{
X_Last = X;
first_trade = true;
InitTicket = OrderSend(NULL,OP_BUY,lotsize,Ask,slippage,Ask-stoploss*Point,Ask+takeprofit*Point,EAComment,1,0,clrDarkBlue);
}
//---
void Sell()
{
X_Last = X;
first_trade = true;
InitTicket = OrderSend(NULL,OP_SELL,lotsize,Bid,slippage,Bid+stoploss*Point,Bid-takeprofit*Point,EAComment,1,0,clrDarkRed);
}
//---
void MartinBuy()
{
if (OrderSelect(InitTicket, SELECT_BY_TICKET) == true)
{
double new_SL = OrderStopLoss();
double new_TP = OrderTakeProfit();
int dont_care = OrderSend(NULL,OP_BUY,lotsize,Ask,slippage,new_SL,new_TP,EAComment+" martin",1,0,clrDarkBlue);
}
}
//---
void MartinSell()
{
if (OrderSelect(InitTicket, SELECT_BY_TICKET) == true)
{
double new_SL = OrderStopLoss();
double new_TP = OrderTakeProfit();
int dont_care = OrderSend(NULL,OP_SELL,lotsize,Bid,slippage,new_SL,new_TP,EAComment+" martin",1,0,clrDarkRed);
}
}
//---
void SearchSignal()
{
X = 0.0; //where 0.0, put here the iCustom for external indicators, or some built-in indicator
if (X >= upper_border)
{
mode = "Sell";
}
else if (X <= lower_border)
{
mode = "Buy";
}
else
{
mode = "";
first_trade = false;
InitTicket = 1;
X_Last = 0.0;
}
}
//---
void CloseCheck()
{
if (OrderSelect(InitTicket, SELECT_BY_TICKET))
{
if (OrderCloseTime() == 0)
{
first_trade = true;
}
else if (OrderCloseTime() != 0)
{
first_trade = false;
}
else
{
return;
}
}
}
//---
void MartinCheck()
{
if (mode == "Buy")
{
if ((X_Last - stepValue) >= X)
{
X_Last = X;
MartinBuy();
}
}
if (mode == "Sell")
{
if ((X_Last + stepValue) <= X)
{
X_Last = X;
MartinSell();
}
}
}
The layout of your code makes it possible for several processes to happen in sequence all on the same tick which I assume you do not want. Try changing your code initially to this and work from there:
void OnTick()
{
SearchSignal();
if(mode=="Buy")
{
if(!first_trade) Buy();
else
{
MartinCheck();
CloseCheck();
}
}
else if(mode=="Sell")
{
if(!first_trade) Sell();
else
{
MartinCheck();
CloseCheck();
}
}
}
Remember to use if(...) else to stop executing all functions when it should only be an either/or situation.

How to make Break even trigger more than one time in one entry

I now trying to make Break Even Code trigger more than one time,
example EA entry is 1.28000 and stop loss 1.28500
if current price reach 1.175000(50pips), sl move to break even such as to 1.28000(5pips).
EA will not make more modify order after condition are meet.
so how to trigger break even again if price reach 1.17000(100pips), sl move to (1.175000)(50 pips)
and again price reach 1.165000(150pips),sl move to 1.17000(100pips)
I want to make
BE_B_M(sl move to(example:5))
and
BE_B_T(price reach(example:50))
as variable and every time price reach target variable change to next value
so became
BE_B_M(sl move to(example:50)) and BE_B_T(price reach(example:100))
The entire code is as follows
extern double BE_T_1 = 50;
extern double BE_M_1 = 5;
extern double BE_T_2 = 100;
extern double BE_M_2 = 50;
extern double BE_T_3 = 150;
extern double BE_M_3 = 100;
double BE_S_M;
double BE_S_T;
void MOVE_BE_1()
{
for(int b=OrdersTotal()-1;b>=0;b--)
{
if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
if(OrderMagicNumber()!=M_Number)continue;
if(OrderSymbol()==Symbol())
if(OrderType()==OP_BUY)
if(Bid-OrderOpenPrice()>BE_S_T*Pips)
if(OrderOpenPrice()>OrderStopLoss())
if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+(BE_S_M*Pips),OrderTakeProfit(),0,CLR_NONE))
Print("eror");
}
for(int s=OrdersTotal()-1;s>=0;s--)
{
if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))
if(OrderMagicNumber()!=M_Number)continue;
if(OrderSymbol()==Symbol())
if(OrderType()==OP_SELL)
if(OrderOpenPrice()-Ask>BE_S_T*Pips)
if(OrderOpenPrice()<OrderStopLoss())
if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-(BE_S_M*Pips),OrderTakeProfit(),0,CLR_NONE))
Print("eror");
}
}
i expect sl will move after price reach every 50pips from entry
Here you can put all the 3 break even levels on one function.
Note: you can use 1 for-loop for both OP_BUY and OP_SELL
Here is my OnInit()
// Global variable
double point;
int OnInit()
{
if(Digits == 5 || Digits == 3) point=Point*10;
else point=Point;
return(INIT_SUCCEEDED);
}
Here is the BreakEven() function
//+------------------------------------------------------------------+
//| Break even the trade at 3 levels |
//+------------------------------------------------------------------+
void BreakEven()
{
// get the stop level for that symbol
double stopLevel = SymbolInfoInteger(Symbol(),SYMBOL_TRADE_STOPS_LEVEL)*Point;
for(int i=OrdersTotal()-1;i>=0;i--)
{
if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
if(OrderMagicNumber()!=M_Number)continue;
if(OrderSymbol()!=Symbol())continue;
if(OrderType()==OP_BUY)
{
double profitPips=Bid-OrderOpenPrice();
double newSL=OrderStopLoss();
if(profitPips>=BE_T_1*point && OrderStopLoss()<OrderOpenPrice()) // Break Even
{
newSL=OrderOpenPrice()+BE_M_1*point;
}
else if(profitPips>=BE_T_3*point) // 150/100
{
newSL=OrderOpenPrice()+BE_M_3*point;
}
else if(profitPips>=BE_T_2*point) // 100/50
{
newSL=OrderOpenPrice()+BE_M_2*point;
}
if(newSL>=OrderStopLoss()+Point && newSL<Bid-stopLevel)
if(!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(newSL,Digits),OrderTakeProfit(),0))
Print("Error at BE: ",GetLastError());
}
else if(OrderType()==OP_SELL)
{
double profitPips=OrderOpenPrice()-Ask;
double newSL=OrderStopLoss();
if(profitPips>=BE_T_1*point && (OrderStopLoss()>OrderOpenPrice() || OrderStopLoss()==0)) // Break Even
{
newSL=OrderOpenPrice()-BE_M_1*point;
}
else if(profitPips>=BE_T_3*point) // 150/100
{
newSL=OrderOpenPrice()-BE_M_3*point;
}
else if(profitPips>=BE_T_2*point) // 100/50
{
newSL=OrderOpenPrice()-BE_M_2*point;
}
if(newSL<=OrderStopLoss()-Point && newSL>Ask+stopLevel)
if(!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(newSL,Digits),OrderTakeProfit(),0))
Print("Error at BE: ",GetLastError());
}
}
}
I didn't test this myself in a trade, but it should work.

Data From Arduino Yun To Google Spreadsheet

I am working on a project where I am sending a timestamp from and Arduino Yun to a Google Spreadsheet. I have a PIR Sensor connected to the Yun. When motion is detected I am sending the value to the spreadsheet. Currently the value is going into one column.
This is not ideal because I want to create a chart from the data so I want the time and date to be in two different columns. Like the sample below.
Arduino Sketch
#include <Bridge.h>
#include <Temboo.h>
#include "TembooAccount.h"
#include <Process.h>
int pir_pin = 8;
Process date;
int hours, minutes, seconds;
int lastSecond = -1;
const String GOOGLE_CLIENT_ID = "";
const String GOOGLE_CLIENT_SECRET = "";
const String GOOGLE_REFRESH_TOKEN = "";
const String SPREADSHEET_TITLE = "";
int numRuns = 1;
int maxRuns = 100;
void setup() {
Serial.begin(9600);
delay(4000);
pinMode(pir_pin, INPUT);
while (!Serial);
Serial.println("Time Check");
if (!date.running()) {
date.begin("date");
date.addParameter("+%T %D");
date.run();
}
Serial.print("Initializing the bridge... ");
Bridge.begin();
Serial.println("Done!\n");
}
void loop()
{
if (digitalRead(pir_pin) == true) {
if (!date.running()) {
date.begin("date");
date.addParameter("+%T %D");
date.run();
}
while (date.available() > 0) {
String timeString = date.readString();
int firstColon = timeString.indexOf(":");
int secondColon = timeString.lastIndexOf(":");
String hourString = timeString.substring(0, firstColon);
String minString = timeString.substring(firstColon + 1, secondColon);
String secString = timeString.substring(secondColon + 1);
hours = hourString.toInt();
minutes = minString.toInt();
lastSecond = seconds;
seconds = secString.toInt();
if (numRuns <= maxRuns) {
Serial.println("Running AppendRow - Run #" + String(numRuns++));
unsigned long now = millis();
Serial.println("Getting sensor value...");
Serial.println("Appending value to spreadsheet...");
TembooChoreo AppendRowChoreo;
AppendRowChoreo.begin();
AppendRowChoreo.setAccountName(TEMBOO_ACCOUNT);
AppendRowChoreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
AppendRowChoreo.setAppKey(TEMBOO_APP_KEY);
AppendRowChoreo.setChoreo("/Library/Google/Spreadsheets/AppendRow");
AppendRowChoreo.addInput("ClientID", GOOGLE_CLIENT_ID);
AppendRowChoreo.addInput("ClientSecret", GOOGLE_CLIENT_SECRET);
AppendRowChoreo.addInput("RefreshToken", GOOGLE_REFRESH_TOKEN);
AppendRowChoreo.addInput("SpreadsheetTitle", SPREADSHEET_TITLE);
String rowData = timeString;
AppendRowChoreo.addInput("RowData", rowData);
unsigned int returnCode = AppendRowChoreo.run();
if (returnCode == 0) {
Serial.println("Success! Appended " + rowData);
Serial.println("");
} else {
while (AppendRowChoreo.available()) {
char c = AppendRowChoreo.read();
Serial.print(c);
}
}
AppendRowChoreo.close();
}
Serial.println("Waiting...");
delay(5000);
}
}
}
How would I alter the code to achieve the above.
I work for Temboo.
You can set multiple columns in the AppendRow Choreo by separating each value in rowData with a comma. For your case, you'd want your rowData to look like this: "19:35:26,4/22/2016". You could try something like timeString.replace(" ",",");.
Hopefully this helps. If you have any other questions, feel free to contact us at https://temboo.com/support

AudioConverter#FillComplexBuffer returns -50 and does not convert anything

I'm strongly following this Xamarin sample (based on this Apple sample) to convert a LinearPCM file to an AAC file.
The sample works great, but implemented in my project, the FillComplexBuffer method returns error -50 and the InputData event is not triggered once, thus nothing is converted.
The error only appears when testing on a device. When testing on the emulator, everything goes great and I get a good encoded AAC file at the end.
I tried a lot of things today, and I don't see any difference between my code and the sample code. Do you have any idea where this may come from?
I don't know if this is in anyway related to Xamarin, it doesn't seem so since the Xamarin sample works great.
Here's the relevant part of my code:
protected void Encode(string path)
{
// In class setup. File at TempWavFilePath has DecodedFormat as format.
//
// DecodedFormat = AudioStreamBasicDescription.CreateLinearPCM();
// AudioStreamBasicDescription encodedFormat = new AudioStreamBasicDescription()
// {
// Format = AudioFormatType.MPEG4AAC,
// SampleRate = DecodedFormat.SampleRate,
// ChannelsPerFrame = DecodedFormat.ChannelsPerFrame,
// };
// AudioStreamBasicDescription.GetFormatInfo (ref encodedFormat);
// EncodedFormat = encodedFormat;
// Setup converter
AudioStreamBasicDescription inputFormat = DecodedFormat;
AudioStreamBasicDescription outputFormat = EncodedFormat;
AudioConverterError converterCreateError;
AudioConverter converter = AudioConverter.Create(inputFormat, outputFormat, out converterCreateError);
if (converterCreateError != AudioConverterError.None)
{
Console.WriteLine("Converter creation error: " + converterCreateError);
}
converter.EncodeBitRate = 192000; // AAC 192kbps
// get the actual formats back from the Audio Converter
inputFormat = converter.CurrentInputStreamDescription;
outputFormat = converter.CurrentOutputStreamDescription;
/*** INPUT ***/
AudioFile inputFile = AudioFile.OpenRead(NSUrl.FromFilename(TempWavFilePath));
// init buffer
const int inputBufferBytesSize = 32768;
IntPtr inputBufferPtr = Marshal.AllocHGlobal(inputBufferBytesSize);
// calc number of packets per read
int inputSizePerPacket = inputFormat.BytesPerPacket;
int inputBufferPacketSize = inputBufferBytesSize / inputSizePerPacket;
AudioStreamPacketDescription[] inputPacketDescriptions = null;
// init position
long inputFilePosition = 0;
// define input delegate
converter.InputData += delegate(ref int numberDataPackets, AudioBuffers data, ref AudioStreamPacketDescription[] dataPacketDescription)
{
// how much to read
if (numberDataPackets > inputBufferPacketSize)
{
numberDataPackets = inputBufferPacketSize;
}
// read from the file
int outNumBytes;
AudioFileError readError = inputFile.ReadPackets(false, out outNumBytes, inputPacketDescriptions, inputFilePosition, ref numberDataPackets, inputBufferPtr);
if (readError != 0)
{
Console.WriteLine("Read error: " + readError);
}
// advance input file packet position
inputFilePosition += numberDataPackets;
// put the data pointer into the buffer list
data.SetData(0, inputBufferPtr, outNumBytes);
// add packet descriptions if required
if (dataPacketDescription != null)
{
if (inputPacketDescriptions != null)
{
dataPacketDescription = inputPacketDescriptions;
}
else
{
dataPacketDescription = null;
}
}
return AudioConverterError.None;
};
/*** OUTPUT ***/
// create the destination file
var outputFile = AudioFile.Create (NSUrl.FromFilename(path), AudioFileType.M4A, outputFormat, AudioFileFlags.EraseFlags);
// init buffer
const int outputBufferBytesSize = 32768;
IntPtr outputBufferPtr = Marshal.AllocHGlobal(outputBufferBytesSize);
AudioBuffers buffers = new AudioBuffers(1);
// calc number of packet per write
int outputSizePerPacket = outputFormat.BytesPerPacket;
AudioStreamPacketDescription[] outputPacketDescriptions = null;
if (outputSizePerPacket == 0) {
// if the destination format is VBR, we need to get max size per packet from the converter
outputSizePerPacket = (int)converter.MaximumOutputPacketSize;
// allocate memory for the PacketDescription structures describing the layout of each packet
outputPacketDescriptions = new AudioStreamPacketDescription [outputBufferBytesSize / outputSizePerPacket];
}
int outputBufferPacketSize = outputBufferBytesSize / outputSizePerPacket;
// init position
long outputFilePosition = 0;
long totalOutputFrames = 0; // used for debugging
// write magic cookie if necessary
if (converter.CompressionMagicCookie != null && converter.CompressionMagicCookie.Length != 0)
{
outputFile.MagicCookie = converter.CompressionMagicCookie;
}
// loop to convert data
Console.WriteLine ("Converting...");
while (true)
{
// create buffer
buffers[0] = new AudioBuffer()
{
NumberChannels = outputFormat.ChannelsPerFrame,
DataByteSize = outputBufferBytesSize,
Data = outputBufferPtr
};
int writtenPackets = outputBufferPacketSize;
// LET'S CONVERT (it's about time...)
AudioConverterError converterFillError = converter.FillComplexBuffer(ref writtenPackets, buffers, outputPacketDescriptions);
if (converterFillError != AudioConverterError.None)
{
Console.WriteLine("FillComplexBuffer error: " + converterFillError);
}
if (writtenPackets == 0) // EOF
{
break;
}
// write to output file
int inNumBytes = buffers[0].DataByteSize;
AudioFileError writeError = outputFile.WritePackets(false, inNumBytes, outputPacketDescriptions, outputFilePosition, ref writtenPackets, outputBufferPtr);
if (writeError != 0)
{
Console.WriteLine("WritePackets error: {0}", writeError);
}
// advance output file packet position
outputFilePosition += writtenPackets;
if (FlowFormat.FramesPerPacket != 0) {
// the format has constant frames per packet
totalOutputFrames += (writtenPackets * FlowFormat.FramesPerPacket);
} else {
// variable frames per packet require doing this for each packet (adding up the number of sample frames of data in each packet)
for (var i = 0; i < writtenPackets; ++i)
{
totalOutputFrames += outputPacketDescriptions[i].VariableFramesInPacket;
}
}
}
// write out any of the leading and trailing frames for compressed formats only
if (outputFormat.BitsPerChannel == 0)
{
Console.WriteLine("Total number of output frames counted: {0}", totalOutputFrames);
WritePacketTableInfo(converter, outputFile);
}
// write the cookie again - sometimes codecs will update cookies at the end of a conversion
if (converter.CompressionMagicCookie != null && converter.CompressionMagicCookie.Length != 0)
{
outputFile.MagicCookie = converter.CompressionMagicCookie;
}
// Clean everything
Marshal.FreeHGlobal(inputBufferPtr);
Marshal.FreeHGlobal(outputBufferPtr);
converter.Dispose();
outputFile.Dispose();
// Remove temp file
File.Delete(TempWavFilePath);
}
I already saw this SO question, but the not-detailed C++/Obj-C related answer doesn't seem to fit with my problem.
Thanks !
I finally found the solution!
I just had to declare AVAudioSession category before converting the file.
AVAudioSession.SharedInstance().SetCategory(AVAudioSessionCategory.AudioProcessing);
AVAudioSession.SharedInstance().SetActive(true);
Since I also use an AudioQueue to RenderOffline, I must in fact set the category to AVAudioSessionCategory.PlayAndRecord so both the offline rendering and the audio converting work.

madvise() function not working

I am trying madvise() to mark allocated memory as mergeable so that two applications having same pages can be merged.
While using the madvise() function it shows "invalid argument".
#include<stdio.h>
#include<sys/mman.h>
#include<stdlib.h>
#include<errno.h>
#define ADDR 0xf900f000
int main()
{
int *var1=NULL,*var2=NULL;
size_t size=0;
size = 1000*sizeof(int);
var1 = (int*)malloc(size);
var2 = (int *)malloc(size);
int i=0;
for(i=0;i<999;i++)
{
var1[i] = 1;
}
for(i=0;i<999;i++)
{
var2[i] = 1;
}
i = -1;
while(i<0)
{
i = madvise((void *)var1, size, MADV_MERGEABLE); //to declare mergeable
printf("%d %p\n", i, var1); //to print the output value
err(1,NULL); //to print the generated error
i = madvise((void *)var2, size, MADV_MERGEABLE); //to declare mergeable
printf("%d\n", i);
}
return 0;
}
Error:
a.out: Invalid argument
Please help me.
Thank You.
You can only merge whole pages. You can't merge arbitrary chunks of data.

Resources