I am a little bit new in this language, but I have the basics.
What I want: open a position with stop loss and take profit.
I want to place an order with 100 euro, and I want to set the stop loss to 10 euros, and set the take profit to 5 euros. But as I see the OrderSend method requires lots for placing the order, and levels for stop loss and take profit.
And my problem is: how to calculate these values based on the euro amounts I want to set?
I searched for some lot-pip-etc calculation on the web, but after all what I tried did not work. This is how I wanted to calculate:
double AmountToTradeInEuro = 100;
double AmountToTakeInEuro = 5;
double AmountToMaxLossInEuro = 10;
double Lots = AmountToTradeInEuro / MarketInfo(Symbol(), MODE_TICKVALUE);
double StopLossLevel = AmountToTakeInEuro / MarketInfo(Symbol(), MODE_TICKVALUE);
double TakeProfitLevel = AmountToMaxLossInEuro / MarketInfo(Symbol(), MODE_TICKVALUE);
OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, StopLossLevel, TakeProfitLevel);
Basically I would like to know how to calculate the Lot for 100 euro and how to calculate the Levels for stoploss and takeprofit.
And are the stoploss and takeprofit levels also lots? Or are they different units?
Welcome to MQL4!
First question is about the account currency - if it is USD (or something else not EUR) - you have to make such convertion. Ok, let me describe what to do with the EUR balance.
You can compute lot size based on the stoploss - in such a case you can get tick value using MarketInfo(_Symbol,MODE_TICKVALUE). But you must know the price level where to exit (stoploss), whether it is 1 pips or 100 pips. Let us think that is 100 ticks (which is equal to 10 pips of 5-digit broker). Then, your lot size is
double lot = AmountToMaxLoss / (MarketInfor(_Symbol, MODE_TICKVALUE) * stoploss), then you have to normalize the result:
double lot_step=MarketInfo(_Symbol, MODE_LOTSTEP);
double result = lot_step * NormalizeDouble(lot / lot_step, 0);
then check that result > MarketInfo(_Symbol, MODE_MINLOT).
About takeprofit - it might be a strange approach to wait for your takeprofit target in the currency instead of the price level but if you need - the way is same.
Related
I have question on take profit point of mt4:
I would like to set take profit point to stop loss * 2, so the code should be:
takeprofit = NormalizeDouble((Ask + ((Ask - stoploss)*Point()*2) + StopLevel*Point()),Digits);
However, it won't works, so anyone know how to fix it? I am new to mq4 coder. Thanks
Remember that you need to differentiate between BUY and SELL orders.
You also look like you are getting confused with stoploss and StopLevel. I'm assuming that your StopLevel is the distance of your stoploss in points.
If that is the case, your code should look something like this (you don't need to reference StopLevel if you already have the distance in Points):
if(ordertype==OP_BUY) takeprofit = NormalizeDouble(Ask+StopLevel*2*Point,Digits);
else takeprofit = NormalizeDouble(Bid-StopLevel*2*Point,Digits);
I am trying to create a EA in mql4, but in OrderSend function, when i use some value instead of zero it show ordersend error 130. Please help to solve this problem
Code line is
int order = OrderSend("XAUUSD",OP_SELL,0.01,Bid,3,Bid+20*0.01,tp,"",0,0,Red);
error number 130 means Invalid stops.
so that means there is a problem with the stops you set with the ordersend function.
I suggest you set it like that:
int order = OrderSend("XAUUSD",OP_SELL,0.01,Bid,3,Bid+20*Point,tp,"",0,0,Red);
so you could use Point instead of hard coding it.
and to check what is the error number means. I think you could refer to: https://book.mql4.com/appendix/errors
You should know that there exists a minimum Stop Loss Size (mSLS) given in pips. "mSLS" changes with the currency and broker. So, you need to put in the OnInit() procedure of your EA a variable to get it:
int mSLS = MarketInfo(symbol,MODE_STOPLEVEL);
The distance (in pips) from your Order Open Price (OOP) and the Stop-Loss Price (SLP) can not be smaller than mSLS value.
I will try to explain a general algorithm I use for opening orders in my EAs, and then apply the constrain on Stop-Loss level (at step 3):
Step 1. I introduce a flag (f) for the type of operation I will open, being:
f = 1 for Buy, and
f = -1 for Sell
You know that there are mql4 constants OP_SELL=1 and OP_BUY=0 (https://docs.mql4.com/constants/tradingconstants/orderproperties).
Once I have defined f, I set my operation type variable to
int OP_TYPE = int(0.5((1+f)*OP_BUY+(1-f)*OP_SELL));
that takes value OP_TYPE=OP_BUY when f=1, while OP_TYPE=OP_SELL when f=-1.
NOTE: Regarding the color of the orders I put them in an array
color COL[2]= {clrBlue,clrRed};
then, having OP_TYPE, I set
color COLOR=COL[OP_TYPE];
Step 2. Similarly, I set the Order Open Price as
double OOP = int(0.5*((1+f)*Ask+(1-f)*Bid));
which takes value OOP=Ask when f=1, while OOP=Bid when f=-1.
Step 3. Then, given my desired Stop Loss in pips (an external POSITIVE parameter of my EA, I named sl) I make sure that sl > SLS. In other words, I check
if (sl <= mSLS) // I set my sl as the minimum allowed
{
sl = 1 + mSLS;
}
Step 4. Then I calculate the Stop-Loss Price of the order as
double SLP = OOP - f * sl * Point;
Step 5. Given my desired Take Profit in pips (an external POSITIVE parameter of my EA, I named tp) I calculate the Take-Profit Price (TPP) of the order as
double TPP = OOP + f * tp * Point;
OBSERVATION: I can not affirm, but, according to mql4 documentation, the minimum distance rule between the stop-loss limit prices and the open price also applies to the take profit limit price. In this case, a "tp" check-up needs to be done, similar to that of the sl check-up, above. that is, before calculating TPP it must be executed the control lines below
if (tp <= mSLS) // I set my tp as the minimum allowed
{
tp = 1 + mSLS;
}
Step 5. I call for order opening with a given lot size (ls) and slippage (slip) on the operating currency pair (from where I get the Ask and Bid values)
float ls = 0.01;
int slip = 3; //(pips)
int order = OrderSend(Symbol(),OP_TYPE,ls,OOP,slip,SLP,TPP,"",0,0,COLOR);
Note that with these few lines it is easy to build a function that opens orders of any type under your command, in any currency pair you are operating, without receiving error message 130, passing to the function only 3 parameters: f, sl and tp.
It is worth including in the test phase of your EA a warning when the sl is corrected for being less than the allowed, this will allow you to increase its value so that it does not violate the stop-loss minimum value rule, while you have more control about the risk of its operations. Remember that the "sl" parameter defines how much you will lose if the order fails because the asset price ended up varying too much in the opposite direction to what was expected.
I hope I could help!
Whilst the other two answers are not necessarily wrong (and I will not go over the ground they have already covered), for completeness of answers, they fail to mention that for some brokers (specifically ECN brokers) you must open your order first, without setting a stop loss or take profit. Once the order is opened, use OrderModify() to set you stop loss and/or take profit.
I have an assignment where ?I need to take a gross pay that is paid in cash and display how many 100s,50s,20s,10s,5s,1s the employee is paid. I'm sure its just my math that is not working but here is my code
COMPUTE W02-PAY-100S = W02-GROSS-PAY / 100
COMPUTE PAY = W02-GROSS-PAY - (W02-PAY-100S * 100)
COMPUTE W02-PAY-50S = PAY / 50
COMPUTE PAY = PAY - (W02-PAY-50S * 50)
COMPUTE W02-PAY-20S = PAY / 20
COMPUTE PAY = PAY - (W02-PAY-20S * 20)
COMPUTE W02-PAY-10S = PAY / 10
COMPUTE PAY = PAY - (W02-PAY-10S * 10)
COMPUTE W02-PAY-5S = PAY / 5
COMPUTE PAY = PAY - (W02-PAY-5S * 5)
COMPUTE W02-PAY-1S = PAY / 1
.
What ends up happening is the first 100s are displayed as 3, then everything else is 0's.
I'd suspect PAY is defined as PIC 9 rather than PIC 9(7) (or whatever), or that there is some problem with the definitions of the other fields you are using (like no integer parts).
However, you're going about it the "wrong" way for COBOL, by making use of the fact that COMPUTE is like an assignment statement in other languages.
Instead COBOL offers more nuance with verbs for maths. Have a look at DIVIDE with GIVING and REMAINDER.
DIVIDE W02-GROSS-PAY BY 100
GIVING NOTES-100
REMAINDER W-RUNNING-BALANCE-LESS-100S
DIVIDE W-RUNNING-BALANCE-LESS-100S
BY 50
GIVING NOTES-50
REMAINDER W-RUNNING-BALANCE-LESS-50S
DIVIDE W-RUNNING-BALANCE-LESS-50S
BY 20
GIVING NOTES-20
REMAINDER W-RUNNING-BALANCE-LESS-20S
DIVIDE W-RUNNING-BALANCE-LESS-20S
BY 10
GIVING NOTES-10
REMAINDER W-RUNNING-BALANCE-LESS-10S
DIVIDE W-RUNNING-BALANCE-LESS-10S
BY 05
GIVING NOTES-05
REMAINDER COINS-01
If you get your COMPUTEs working, you don't need the last one (divide by one gives you as the answer the original number). With the COMPUTEs you are doing a lot more work than necessary in COBOL.
Now that you know about DIVIDE, also look at MULTIPLY, ADD and SUBTRACT.
To complete the picture, look at the intrinsic functions like INTEGER and MOD. The MOD and more, you have above. The INTEGER is unnecessary because a simple MOVE to a field without a fractional part will get there. A MOVE to a field without an integer part will get you the fraction.
Don't, necessarily, look for something which allows you to do it as you would in another language. You may "pass" your COBOL module that way, but you won't really learn COBOL.
I have a panel data set for which I would like to calculate moving averages across years.
Each year is a variable for which there is an observation for each state, and I would like to create a new variable for the average of every three year period.
For example:
P1947=rmean(v1943 v1944 v1945), P1947=rmean(v1944 v1945 v1946)
I figured I should use a foreach loop with the egen command, but I'm not sure about how I should refer to the different variables within the loop.
I'd appreciate any guidance!
This data structure is quite unfit for purpose. Assuming an identifier id you need to reshape, e.g.
reshape long v, i(id) j(year)
tsset id year
Then a moving average is easy. Use tssmooth or just generate, e.g.
gen mave = (L.v + v + F.v)/3
or (better)
gen mave = 0.25 * L.v + 0.5 * v + 0.25 * F.v
More on why your data structure is quite unfit: Not only would calculation of a moving average need a loop (not necessarily involving egen), but you would be creating several new extra variables. Using those in any subsequent analysis would be somewhere between awkward and impossible.
EDIT I'll give a sample loop, while not moving from my stance that it is poor technique. I don't see a reason behind your naming convention whereby P1947 is a mean for 1943-1945; I assume that's just a typo. Let's suppose that we have data for 1913-2012. For means of 3 years, we lose one year at each end.
forval j = 1914/2011 {
local i = `j' - 1
local k = `j' + 1
gen P`j' = (v`i' + v`j' + v`k') / 3
}
That could be written more concisely, at the expense of a flurry of macros within macros. Using unequal weights is easy, as above. The only reason to use egen is that it doesn't give up if there are missings, which the above will do.
FURTHER EDIT
As a matter of completeness, note that it is easy to handle missings without resorting to egen.
The numerator
(v`i' + v`j' + v`k')
generalises to
(cond(missing(v`i'), 0, v`i') + cond(missing(v`j'), 0, v`j') + cond(missing(v`k'), 0, v`k')
and the denominator
3
generalises to
!missing(v`i') + !missing(v`j') + !missing(v`k')
If all values are missing, this reduces to 0/0, or missing. Otherwise, if any value is missing, we add 0 to the numerator and 0 to the denominator, which is the same as ignoring it. Naturally the code is tolerable as above for averages of 3 years, but either for that case or for averaging over more years, we would replace the lines above by a loop, which is what egen does.
There is a user written program that can do that very easily for you. It is called mvsumm and can be found through findit mvsumm
xtset id time
mvsumm observations, stat(mean) win(t) gen(new_variable) end
I am trying to round big numbers to the nearest 1 hundred, by dividing by 100, rounding and then multiplying by 100.
However, the big number values are losing value when converting to floats.
This is the problem part:
int bigInt = 99222049;
float bigFloat = bigInt / 100.0;
NSLog(#"%d %f", bigInt, bigFloat);
Output:
99222049 992220.500000
Would like it to be:
99222049 992220.49
Sorry if this is a stupid question! Would be grateful for advice. Thanks.
Your basic problem is float rounding. You cannot express arbitrary decimal fractions as floats (or doubles). In binary, 1/10 is 0.00011001100110011... It never terminates, just like 1/3 is 0.33333... in decimal. So you need to do your work in base 10, not base 2, if you want your results to round nicely in base 10. There are two approaches in Cocoa:
You can do your work purely with integer math, no floating point. See Rounding integers to nearest ten or hundred in C for an example of how to do this.
Alternately, since this is ObjC, you can use NSDecimalNumber, which will allow you to perform all your math in base 10.
You need to change your float to a double.
int bigInt = 99222049;
double bigFloat = bigInt / 100.0;
NSLog(#"%u %f", bigInt, bigFloat);
Outputs:
99222049 992220.490000
Change your code to this and the output should show as you desire. I changed the float to a double and .2 before f to show only 2 decimal places.
int bigInt = 99222049;
double bigFloat = bigInt / 100.0;
NSLog(#"%d %.2f", bigInt, bigFloat);
This is what shows in console
99222049 992220.49
I hope this helps, cheers, Jim.