MySQL evaluate a string as a math expression - mysql

Currently, I'm using this function:
DELIMITER //
CREATE FUNCTION SUM_OF_LIST(s TEXT)
RETURNS DOUBLE
DETERMINISTIC
NO SQL
BEGIN
DECLARE res DOUBLE DEFAULT 0;
WHILE INSTR(s, ",") > 0 DO
SET res = res + SUBSTRING_INDEX(s, ",", 1);
SET s = MID(s, INSTR(s, ",") + 1);
END WHILE;
RETURN res + s;
END //
DELIMITER ;
#Found here:
Summing a comma separated column in MySQL 4 (not 5)
To sum MySQL results like this:
30.48, 7.41, 5.01, 18.01, 11.07, 9.12, 45.90, 11.56, 37.62, 23.34, 2.23, 8.46, 49.20, 7.82, 7.11, 11.22, 581.79, 15.42, 22.68, 15.06, 115.20, 4.82, 69.30, 77.00, 6.90, 3.92, 43.26, 5.63, 5.40, 9.08, 6.96, 10.54, 4.35, 29.76, 32.79, 20.16, 26.22, 9.81, 11.86, 6.34, 10.28, 38.08, 35.25, 58.95, 6.32, 50.92, 31.04, 58.22, 22.23, 22.52, 18.46, 8.09, 8.30, 36.54, 14.55, 4.35, 9.92, 4.45, 32.46, 55.92, 61.02, 26.40, 4.05, 6.36, 3.38, 20.61, 19.02, 9.30, 9.76, 45.42, 11.79, 14.45, 14.88, 24.38, 12.69, 28.80, 38.10, 31.86, 16.47, 46.74, 70.80, 6.27, 8.20, 16.47, 61.80, 61.80, 7.70, 14.20, 19.83, 19.64, 19.62, 81.60, 56.52, 56.70, 28.16, 1.71, 16.58, 6.09, 11.90, 71.44, 174.45, 5.89, 9.23, 8.75, 15.12, 7.40, 21.78, 8.04, 10.86, 19.02, 8.76, 76.23, 7.06, 19.80, 65.52, 16.12, 9.99, 11.41, 10.29, 9.45, 56.64, 12.90, 24.30, 74.29, 33.62, 13.50, 9.71, 9.60, 69.30, 19.25, 28.16, 27.86, 9.16, 25.80, 30.84, 10.58, 68.04, 5.03, 19.50, 70.20, 8.60, 20.22, 126.27, 23.01, 92.40, 37.26, 19.62, 78.48, 74.46, 11.73, 88.40, 25.30, 8.13, 181.44, 31.23, 9.12, 22.23, 50.92, 3.69, 4.06, 8.75, 8.75, 13.40, 14.04, 14.52, 26.64, 79.74, 8.96, 16.20, 15.20, 26.61, 9.45, 42.60, 21.84, 565.74, 108.24, 18.80, 13.56, 5.97, 16.47, 61.45, 8.00, 28.40, 34.92, 33.75, 5.04, 24.75, 13.00, 78.00, 9.90, 14.92, 11.16, 12.16, 32.04, 9.81, 7.98, 36.84, 15.20, 7.09, 6.86, 31.32, 20.37, 6.30, 186.30, 7.09, 4.50, 4.93, 25.68, 2.25, 13.26, 29.02, 17.90, 11.10, 5.01, 7.41, 42.60, 15.42, 13.50, 33.00, 70.80, 6.38, 9.93, 7.58, 11.76, 35.84, 12.60, 17.20, 17.20, 74.29, 21.84, 3.15, 554.73, 216.00, 27.14, 12.65, 29.22, 33.66, 7.98, 7.69, 9.84, 8.10, 5.48, 21.96, 74.76, 30.30, 118.68, 3.78, 19.32, 17.40, 20.16, 10.77, 21.54, 12.13, 11.68, 16.92, 16.47, 7.01, 3.72, 20.58, 100.75, 4.46, 20.84, 14.42, 18.96, 8.50, 10.30, 11.73, 6.70, 9.12, 31.32, 94.38, 17.91, 7.70, 18.81, 16.08, 4.54, 14.82, 19.86, 47.52, 3.94, 50.92, 3.07, 9.23, 9.23, 8.75, 15.84, 2.25, 7.41, 16.08, 3936.00, 32.22, 11.82, 8.46, 33.93, 15.12, 27.37, 9.12, 16.81, 50.43, 568.26, 15.42, 446.49, 25.29, 7.50, 3.92, 7.08, 23.82, 18.66, 33.60, 9.68, 18.81, 20.46, 14.86, 4.39, 16.47, 16.93, 30.48, 6.87, 145.80, 147.75, 47.11, 4.56, 15.40, 71.15, 16.92, 30.54, 10.30, 10.92, 5.85, 9.81, 57.84, 55.68, 1507.20, 6.70, 10.30, 7.68, 24.00, 27.48, 7.58, 19.25, 20.58, 4.70, 8.06, 19.03, 9.23, 9.23, 9.30, 17.74, 11.85, 22.25, 5.42, 3.40, 53.76, 9.36, 15.33, 15.30, 53.76, 8.46, 15.60, 7.58, 83.93, 15.14, 61.52, 7.58, 6.88, 7.57, 14.36, 30.27, 229.50, 121.77, 13.53, 5.47, 32.61, 7.70, 100.62, 30.54, 30.81, 4.50, 19.96, 5.06, 36.84, 51.24, 3.33, 7.80, 14.84, 8.06, 15.36, 6.88, 17.70, 10.18, 26.08, 10.74, 13.53, 17.79, 78.48, 12.36, 22.80, 26.04, 37.62, 11.22
This function works, but I wish to sum large amount of data, in my tests I'm can evaluate around 12 Mi math operations in ~30 segs.
But when it run in a normalized database I can sumarize this task in < 0.5 seg.
It's possible evalute some string like "10.02 + 1.03 + 4.01 + 5.07" as a math expression?
I already try to use CAST eval, but eval don't return anything :(

Related

ultimate short custom number formatting - K, M, B, T, etc., Q, D, Googol

is there a way how to custom format ridiculously large numbers (at least up to 10^100 in both ways) in google sheets:
thousands > K
millions > M
billions > B
trillions > T
etc...
negative quadrillions > Q
decillions > D
either via:
internal custom number formatting
formula (array formula ofc)
script similar to this one just extended to cover more ground
10000.1 10.0K
100 100.0
1000 1.0K
10000 10.0K
-100000 -100.0K
45646454 45.6M
5654894844216 5.7T
4655454544 4.7B
46546465455511 46.5T
-46546465455511 -46.5T
4654646545551184854556546454454400000000000000000000000000010000000 4.7U
-1000.9999 -1.0K
-100.8989 -100.9
-20.354 -20.4
1.03 1.0
22E+32 2.2D
internal custom number formatting solution:
sadly, the internal formatting in google sheets is by default able to work with only 3 types of numbers:
positive (1, 2, 5, 10, ...)
negative (-3, -9, -7, ...)
zero (0)
this can be tweaked to show custom formatting like thousands K, millions M and regular small numbers:
[>999999]0.0,,"M";[>999]0.0,"K";0
or only thousands K, millions M, billions B
[<999950]0.0,"K";[<999950000]0.0,,"M";0.0,,,"B"
or only negative thousands K, negative millions M, negative billions B
[>-999950]0.0,"K";[>-999950000]0.0,,"M";0.0,,,"B"
or only millions M, billions B, trillions T:
[<999950000]0.0,,"M";[<999950000000]0.0,,,"B";0.0,,,,"T"
or only numbers from negative million M to positive million M:
[>=999950]0.0,,"M";[<=-999950]0.0,,"M";0.0,"K"
but you always got only 3 slots you can use, meaning that you can't have trillions as the 4th type/slot. fyi, the 4th slot exists, but it's reserved for text. to learn more about internal formatting in google sheets see:
https://developers.google.com/sheets/api/guides/formats#meta_instructions
https://www.benlcollins.com/spreadsheets/google-sheets-custom-number-format/
formula (array formula) solution:
the formula approach is more versatile... first, you will need to decide on the system/standard you want to use (American, European, Greek, International, Unofficial, etc...):
en.wikipedia.org/wiki/Names_of_large_numbers
en.wikipedia.org/wiki/Metric_prefix
simple.wikipedia.org/wiki/Names_for_large_numbers
home.kpn.nl/vanadovv/BignumbyN
after that try:
=INDEX(REGEXREPLACE(IFNA(TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1,
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")&VLOOKUP(ABS(A:A)*1, {{10^SEQUENCE(34, 1, 3, 3)},
{"K "; "M "; "B "; "T "; "Qa "; "Qi "; "Sx "; "Sp "; "O "; "N "; "D "; "Ud ";
"Dd "; "Td "; "Qad"; "Qid"; "Sxd"; "Spd"; "Od "; "Nd "; "V "; "Uv "; "Dv "; "Tv ";
"Qav"; "Qiv"; "Sxv"; "Spv"; "Ov "; "Nv "; "Tr "; "Ut "; "Dt "; "Tt "}}, 2, 1),
IF(ISBLANK(A:A),, TEXT(A:A, "0.0 "))), "^0\.0 $", "0 "))
works with positive numbers
works with negative numbers
works with zero
works with decimal numbers
works with numeric values
works with plain text numbers
works with scientific notations
works with blank cells
works up to googol 10^104 in both ways
extra points if you are interested in how it works...
let's start with virtual array {{},{}}. SEQUENCE(34, 1, 3, 3) will give us 34 numbers in 1 column starting from number 3 with the step of 3 numbers:
these will be used as exponents while rising 10 on the power ^
so our virtual array will be:
next, we insert it as the 2nd argument of VLOOKUP where we check ABS absolute values (converting negative values into positive) of A column multiplied by *1 just in case values of A column are not numeric. via VLOOKUP we return the second 2 column and as the 4th argument, we use approximate mode 1
numbers from -999 to 999 will intentionally error out at this point so we could later use IFNA to "fix" our errors with IF(A:A=IF(,,),, TEXT(A:A, "#.0 ")) translated as: if range A:A is truly empty ISBLANK output nothing, else format A column with provided pattern #.0 eg. if cell A5 = empty, the output will be blank cell... if -999 < A5=50 < 999 the output will be 50.0
and the last part:
TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1,
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")
ABS(A:A) to convert negative numbers into positive. INT to remove decimal numbers if any. TEXT(, "0") to convert scientific notations 3E+8 into regular numbers 300000000. LEN to count digits. -1 to correct for base10 notation. VLOOKUP above-constructed number in SEQUENCE of 35 numbers in 1 column, this time starting from number 0 ,, with the step of 3 numbers. return via VLOOKUP the first 1 column (eg. the sequence) in approximate mode 1 of vlookup. insert this number as exponent when rising the 10 on power ^. and take values in A column and divide it by the above-constructed number 10 raised on the power ^ of a specific exponent. and lastly, format it with TEXT as #.0
to convert ugly 0.0 into beautiful 0 we just use REGEXREPLACE. and INDEX is used instead of the longer ARRAYFORMULA.
sidenote: to remove trailing spaces (which are there to add nice alignment lol) either remove them from the formula or use TRIM right after INDEX.
script solution:
gratitude to #TheMaster for covering this
here is a mod of it:
/**
* formats various numbers according to the provided short format
* #customfunction
* #param {A1:C100} range a 2D array
* #param {[X1:Y10]} database [optional] a real/virtual 2D array
* where the odd column holds exponent of base 10
* and the even column contains format suffixes
* #param {[5]} value [optional] fix suffix to fixed length
* by padding spaces (only if the second parameter exists)
*/
// examples:
// =CSF(A1:A)
// =CSF(2:2; X5:Y10)
// =CSF(A1:3; G10:J30)
// =CSF(C:C; X:Y; 2) to use custom alignment
// =CSF(C:C; X:Y; 0) to remove alignment
// =INDEX(TRIM(CSF(A:A))) to remove alignment
// =CSF(B10:D30; {3\ "K"; 4\ "TK"}) for non-english sheets
// =CSF(E5, {2, "deci"; 3, "kilo"}) for english sheets
// =INDEX(IF(ISERR(A:A*1); A:A; CSF(A:A))) to return non-numbers
// =INDEX(IF((ISERR(A:A*1))+(ISBLANK(A:A)), A:A, CSF(A:A*1))) enforce mode
function CSF(
range,
database = [
[3, 'K' ], //Thousand
[6, 'M' ], //Million
[9, 'B' ], //Billion
[12, 'T' ], //Trillion
[15, 'Qa' ], //Quadrillion
[18, 'Qi' ], //Quintillion
[21, 'Sx' ], //Sextillion
[24, 'Sp' ], //Septillion
[27, 'O' ], //Octillion
[30, 'N' ], //Nonillion
[33, 'D' ], //Decillion
[36, 'Ud' ], //Undecillion
[39, 'Dd' ], //Duodecillion
[42, 'Td' ], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od' ], //Octodecillion
[60, 'Nd' ], //Novemdecillion
[63, 'V' ], //Vigintillion
[66, 'Uv' ], //Unvigintillion
[69, 'Dv' ], //Duovigintillion
[72, 'Tv' ], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov' ], //Octovigintillion
[90, 'Nv' ], //Novemvigintillion
[93, 'Tr' ], //Trigintillion
[96, 'Ut' ], //Untrigintillion
[99, 'Dt' ], //Duotrigintillion
[100, 'G' ], //Googol
[102, 'Tt' ], //Tretrigintillion or One Hundred Googol
],
value = 3
) {
if (
database[database.length - 1] &&
database[database.length - 1][0] !== 0
) {
database = database.reverse();
database.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(value, ' ');
const decim = 1 // round to decimal places
const separ = 0 // separate number and suffix
const anum = Math.abs(num);
if (num === 0)
return '0' + ' ' + ' '.repeat(separ) + ' '.repeat(decim) + pad3();
if (anum > 0 && anum < 1)
return String(num.toFixed(decim)) + ' '.repeat(separ) + pad3();
for (const [exp, suffix] of database) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(decim)
}${' '.repeat(separ) + pad3(suffix)}`;
}
};
return customFunctionRecurse_(
range, CSF, addSuffix, database, value, true
);
}
function customFunctionRecurse_(
array, mainFunc, subFunc, ...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}
sidenote 1: this script does not need to be authorized priorly to usage
sidenote 2: cell formatting needs to be set to Automatic or Number otherwise use enforce mode
extra:
convert numbers into plain text strings/words
convert array of numbers into plain text strings/words
convert custom formatted numbers into numeric numbers/values
convert text string datetime into duration value
convert text string formatted numbers into duration
convert your age into years-months-days
For almost all practical purposes we can use Intl compact format to achieve this functionality.
/**
* Utility function needed to recurse 2D arrays
*/
function customFunctionRecurse_(
array,
mainFunc,
subFunc,
...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}
/**
* Simple custom formating function using Intl
* #see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
* #customfunction
* #author TheMaster https://stackoverflow.com/users/8404453
* #param {A1:D2} numArr A 2D array
* #returns {String[][]}Compact Intl formatted 2D array
*/
function format(numArr) {
const cIntl = new Intl.NumberFormat('en-GB', {
notation: 'compact',
compactDisplay: 'short',
});
return customFunctionRecurse_(numArr, format, (num) => cIntl.format(num));
}
But for extreme ends or custom formatting, We need to use a custom script:
/**
* Formats various numbers according to the provided format
* #customfunction
* #author TheMaster https://stackoverflow.com/users/8404453
* #param {A1:D2} numArr A 2D array
* #param {X1:Y2} formatArr [optional] A format 2D real/virtual array
* with base 10 power -> suffix mapping
* eg: X1:3 Y1:K represents numbers > 10^3 should have a K suffix
* #param {3} suffixPadLength [optional] Fix suffix to fixed length by padding spaces
* #returns {String[][]} Formatted 2D array
*/
function customFormat(
numArr,
formatArr = [
/**This formatArr array is provided by
* by player0 https://stackoverflow.com/users/5632629/
* #see https://stackoverflow.com/questions/69773823#comment123503634_69809210
*/
[3, 'K'], //Thousand
[6, 'M'], //Million
[9, 'B'], //Billion
[12, 'T'], //Trillion
[15, 'Qa'], //Quadrillion
[18, 'Qi'], //Quintillion
[21, 'Sx'], //Sextillion
[24, 'Sp'], //Septillion
[27, 'O'], //Octillion
[30, 'N'], //Nonillion
[33, 'D'], //Decillion
[36, 'Ud'], //Undecillion
[39, 'Dd'], //Duodecillion
[42, 'Td'], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od'], //Octodecillion
[60, 'Nd'], //Novemdecillion
[63, 'V'], //Vigintillion
[66, 'Uv'], //Unvigintillion
[69, 'Dv'], //Duovigintillion
[72, 'Tv'], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov'], //Octovigintillion
[90, 'Nv'], //Novemvigintillion
[93, 'Tr'], //Trigintillion
[96, 'Ut'], //Untrigintillion
[99, 'Dt'], //Duotrigintillion
[102, 'G'], //Googol
],
suffixPadLength = 3,
inRecursion = false
) {
if (!inRecursion) {
formatArr = formatArr.reverse();
formatArr.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(suffixPadLength, ' '); //pad 3 spaces if necessary
const anum = Math.abs(num);
if (num === 0) return '0' + pad3();
if (anum > 0 && anum < 1) return String(num.toFixed(2)) + pad3();
for (const [exp, suffix] of formatArr) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(2)}${pad3(suffix)}`;
}
};
return customFunctionRecurse_(
numArr,
customFormat,
addSuffix,
formatArr,
suffixPadLength,
true
);
}
Usage:
=CUSTOMFORMAT(A1:A5,{{3,"k"};{10,"G"}})
Tells custom function to use k for numbers>10^3 and G for 10^10
Illustration:
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
/**
* Utility function needed to map 2D arrays
*/
function customFunctionRecurse_(array, mainFunc, subFunc, extraArgToMainFunc) {
if (Array.isArray(array))
return array.map((e) => mainFunc(e, extraArgToMainFunc));
else return subFunc(array);
}
/**
* Simple custom formating function using Intl
* #see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
* #customfunction
* #param {A1:D2} A 2D array
* #returns {String[][]}Compact Intl formatted 2D array
*/
function format(numArr) {
const cIntl = new Intl.NumberFormat('en-GB', {
notation: 'compact',
compactDisplay: 'short',
});
return customFunctionRecurse_(numArr, format, (num) => cIntl.format(num));
}
/**
* Formats various numbers according to the provided format
* #customfunction
* #param {A1:D2} A 2D array
* #param {X1:Y2=} [optional] A format 2D real/virtual array
* with base 10 power -> suffix mapping
* eg: X1:3 Y1:K represents numbers > 10^3 should have a K suffix
* #returns {String[][]} Formatted 2D array
*/
function customFormat(
numArr,
formatArr = [
//sample byte => kb formatting
[3, 'kb'],
[6, 'mb'],
[9, 'gb'],
[12, 'tb'],
]
) {
//console.log({ numArr, formatArr });
if (
formatArr[formatArr.length - 1] &&
formatArr[formatArr.length - 1][0] !== 0
) {
formatArr = formatArr.reverse();
formatArr.push([0, '']);
}
const addSuffix = (num) => {
const anum = Math.abs(num);
if (num === 0) return '0.00';
if (anum > 0 && anum < 1) return String(num.toFixed(2));
for (const [exp, suffix] of formatArr) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(2)}${suffix}`;
}
};
return customFunctionRecurse_(numArr, customFormat, addSuffix, formatArr);
}
console.log(
customFormat([
[
0,
1000,
153,
12883255,
235688235123,
88555552233355888,
-86555,
0.8523588055,
Math.pow(10, 15),
],
])
);
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
sometimes when we deal with nuclear physics we need to shorten the time so this is how:
=INDEX(IF(ISBLANK(A2:A),,TEXT(TRUNC(TEXT(IF(A2:A*1<1,
TEXT(A2:A*1, "0."&REPT(0, 30))*VLOOKUP(A2:A*1, {SORT({0; 1/10^SEQUENCE(9, 1, 3, 3)}),
{0; 10^SORT(SEQUENCE(9, 1, 3, 3), 1,)}}, 2, 1), TEXT(A2:A*1, REPT(0, 30))/
VLOOKUP(A2:A*1, TEXT({1; 60; 3600; 86400; 31536000; 31536000*10^SEQUENCE(8, 1, 3, 3)},
{"#", "#"})*1, 2, 1)), "0."&REPT("0", 30)), 3), "0.000")&" "&
VLOOKUP(A2:A*1, {SORT({0; 1/10^SEQUENCE(9, 1, 3, 3);
{1; 60; 3600; 86400; 31536000}; 31536000*10^SEQUENCE(8, 1, 3, 3)}), FLATTEN(SPLIT(
"s ys zs as fs ps ns μs ms s m h d y ky My Gy Ty Py Ey Zy Yy", " ",,))}, 2, 1)))
it's a simple conversion from seconds into abbreviation utilizing the International System of Units where:
in seconds
____________________________________
ys = yoctosecond = 0.000000000000000000000001
zs = zeptosecond = 0.000000000000000000001
as = attosecond = 0.000000000000000001
fs = femtosecond = 0.000000000000001
ps = pikosecond = 0.000000000001
ns = nanosecond = 0.000000001
μs = microsecond = 0.000001
ms = millisecond = 0.001
s = second = 1
m = minute = 60
h = hour = 3600
d = day = 86400
y = year = 31536000
ky = kiloyear = 31536000000
My = megayear = 31536000000000
Gy = gigayear = 31536000000000000
Ty = terayear = 31536000000000000000
Py = petayear = 31536000000000000000000
Ey = exayear = 31536000000000000000000000
Zy = zettayear = 31536000000000000000000000000
Yy = yottayear = 31536000000000000000000000000000

callback function throws unexpected "nonconformant arguments" error

I'm using GNU Octave, version 4.4.1. I'm trying to make an interactive plot of a simple oscillator by including two sliders which would allow the initial velocity and oscillator mass to be changed.
The plot itself shows fine, as well as the script with one slider (for velocity). Here's a part of that script with the callback function:
function titranje_ia1 (hslider, event)
v0 = get ( hslider, "value" );
m = 1;
k = 1;
t = 0:0.1:30;
x = v0*sin(sqrt(k/m)*t);
axes ('position', [0.1, 0.2, 0.8, 0.75]);
h = plot ( t, x );
axis ([0 30 -11 11]);
set (h, "linewidth", 2);
set (gca, "xlabel", "t (s)", "ylabel", "x (m)", "fontsize", 12);
set (gca, 'XTick', 0:pi:10*pi)
set (gca, 'XTickLabel', {'0','\pi','2\pi','3\pi','4\pi','5\pi','6\pi','7\pi','8\pi','9\pi','10\pi'})
grid on;
l = legend (sprintf('v0 = %f', v0));
set (l, "fontsize", 12)
endfunction
However, when I include a second slider
function titranje_ia2 (hslider1, hslider2, event)
v0 = get ( hslider1, "value" );
m = get ( hslider2, "value" );
k = 1;
t = 0:0.1:30;
x = v0.*sin(sqrt(k./m).*t);
axes ('position', [0.1, 0.2, 0.8, 0.75]);
h = plot ( t, x );
axis ([0 30 -11 11]);
set (h, "linewidth", 2);
set (gca, "xlabel", "t (s)", "ylabel", "x (m)", "fontsize", 12);
set (gca, 'XTick', 0:pi:10*pi)
set (gca, 'XTickLabel', {'0','\pi','2\pi','3\pi','4\pi','5\pi','6\pi','7\pi','8\pi','9\pi','10\pi'})
grid on;
l = legend (sprintf('v0 = %f', v0));
set (l, "fontsize", 12)
endfunction
I receive an error:
error: titranje_ia2: product: nonconformant arguments (op1 is 0x0, op2 is 1x301)
execution error in graphics callback function
Since I know that 'k' is a scalar and 't' a vector (but I'm not sure what v0 and m would be; I suppose scalars), I included an elementwise operations in function 'x' definition. 't' size is 1x301, so I assume that 'sqrt(k./m)' is 0x0 (as seen by Octave). Shouldn't it be 1x1?
Indeed, when I try
size(m)
I receive ans = 0 0 (for size(v0) I get ans = 1 1). Could it be that there is a problem with slider definition? I include at the end both slider definitions:
%Definiramo ui element: 'klizac' za v0
hslider1 = uicontrol (
"style", "slider",
"units", "normalized",
"position", [0.1, 0.0, 0.8, 0.1],
"min", 1,
"max", 10,
"value", 4,
"callback", #titranje_ia2
);
%Definiramo ui element: 'klizac' za m
hslider2 = uicontrol (
"style", "slider",
"units", "normalized",
"position", [0.1, 0.05, 0.8, 0.1],
"min", 1,
"max", 10,
"value", 1,
"callback", #titranje_ia2
);
Thank You in advance!
Best regards,
Igor
You seem to be misunderstanding a bit how callbacks work. Whenever you interact with a uicontrol object, the associated callback is always called automatically with [at least] two arguments: the first is always the 'handle' of the corresponding uicontrol object that triggerred he callback, and the second is the type of 'event' that was triggered. Therefore your callback function needs to always have a signature of callbackname( hndl, evt ) at the very least, so that it can handle those two arguments passed to it by default.
You can specify extra arguments to passed to the callback if you want, but these will necessarily be interpreted as 3rd, 4th, and so on, inside the callback function (see example below).
If you have a case like yours where you don't really care where the event originated from, and you want to affect (or in this case 'read from') two existing uicontrols in a single callback, regardless which one triggerred the event, the simplest thing to do is to make both slider handles to be extra arguments to the callback, and simply ignore the first argument (i.e. the 'active handle') inside your callback. (in fact, you're already ignoring the 'event' argument too!).
Here's an example:
%% In file makesliders.m
function makesliders()
% Label and slider for initial velocity
IV_label = uicontrol( 'style', 'text' , 'units', 'normalized', 'position', [0.10, 0.025, 0.30, 0.075], 'string', 'Initial Velocity' );
IV_slider = uicontrol( 'style', 'slider', 'units', 'normalized', 'position', [0.45, 0.025, 0.50, 0.075], 'min', 1, 'max', 10 );
% Label and slider for oscillator mass
OM_label = uicontrol( 'style', 'text' , 'units', 'normalized', 'position', [0.10, 0.125, 0.30, 0.075], 'string', 'Oscillator Mass ' );
OM_slider = uicontrol( 'style', 'slider', 'units', 'normalized', 'position', [0.45, 0.125, 0.50, 0.075], 'min', 1, 'max', 10 );
% Set callbacks and initial values to IV and OM sliders, and plot initial graph
v0_init = 4; m_init = 1;
set( IV_slider, 'value', v0_init, 'callback', { #slider_callback, IV_slider, OM_slider } );
set( OM_slider, 'value', m_init , 'callback', { #slider_callback, IV_slider, OM_slider } );
plot_oscillation( v0_init, m_init );
endfunction
function slider_callback (active_handle, event, IV_slider, OM_slider )
v0 = get( IV_slider, 'value' );
m = get( OM_slider, 'value' );
plot_oscillation( v0, m );
endfunction
function plot_oscillation( v0, m )
k = 1;
t = 0 : 0.1 : 30;
x = v0 * sin( sqrt( k / m ) * t );
h = plot( t, x ); set( h , 'linewidth', 2);
set( gca, 'position', [0.1, 0.325, 0.85, 0.650], 'xlim', [0, 30], 'ylim', [-11, 11], 'xlabel', 't (s)', 'ylabel', 'x (m)', 'fontsize', 12, 'xtick', [0 : pi : 10 * pi], 'xticklabel', strcat( arrayfun( #num2str, 0:10, 'uniformoutput', false ), '\pi' ), 'xgrid', 'on', 'ygrid', 'on' );
l = legend( sprintf( 'v0 = %.2f, m = %.2f', v0, m ) ); set( l, 'fontsize', 12 );
endfunction

How to export more than 63 parameters using a FileWrite() function in MQL4?

Below I have the full code that allows me to download the data of one currency pair, the USDJPY
#property copyright ""
#property link ""
#property version "1.00"
#property strict
datetime LastActiontime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
start("USDJPY",60); // This will produce daily history for GBPUSD
// Copy the above line of code for each currency pair and timeframe, and then press F5 to recompile (or restart MT4)
// First parameter must be a valid currency pair, e.g. GBPUSD
// Second parameter must be valid timeframe, i.e. one of 1, 5, 15, 30, 60 (=H1), 240 (=H4), 1440 (daily), 10080 (weekly), 43200 (monthly)
// To use the currently displayed chart: out_hist(Symbol(),Period());
return(0); // return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
//void OnTick()
//{
//---
// Comparing LastActionTime with the current starting time for the candle
// if(LastActiontime!=Time[0]){ //Code to execute once in the bar
// Print("This code is executed only once in the bar started ",Time[0]);
// LastActiontime=Time[0];
// }
//}
int start(string ccy, int tf)
{
string fname = ccy + "," + tf + ".csv"; // Same folder for each TF (...\experts\files)
//string fname = "TF-" + tf + "\\" + ccy + "," + tf + ".csv"; // Different subfolder for each timeframe
int handle = FileOpen(fname, FILE_CSV|FILE_WRITE, ","); // "," means that output data will be separated by commas; change if necessary
if(LastActiontime!=Time[0] && handle>0)
{
FileWrite(handle,"Date,Time,Open,Low,High,Close,Volume,RSI,AC,AD,ADX,Alligator,AO,ATR,BearsPower,Bands,BullsPower,CCI,DeMarker,Envelopes,Force,Fractals,Gator,Ichimoku,BWMFI,Momentum,MFI,MA,OsMA,MACD,OBV,SAR,RVI,StdDev,Stochastic,WPR,Vortex_minus,Vortex_positive,CCI13,CCI12,CCI11,CC10,CCI9,CCI8,CCI7,CCI6,CCI5,CCI4,CCI3,CCI15,CCI16,CCI17,CCI18,CCI19,CCI20,CCI21,CCI22,CCI24,CCI25,CCI26,sstoch"); // This writes the Header record to the file (change or remove to suit)
// for(int i=0; i<iBars(ccy,tf); i++) // Use descending date sequence
for(int i=iBars(ccy,tf)-1; i>=0; i--) // Use ascending date sequence
{
string date1 = TimeToStr(iTime(ccy,tf,i),TIME_DATE);
date1 = StringSubstr(date1,5,2) + "-" + StringSubstr(date1,8,2) + "-" + StringSubstr(date1,0,4);
// NOTE: StringSubstr(date1,5,2) is the MONTH
// StringSubstr(date1,8,2) is the DAY
// StringSubstr(date1,0,4) is the YEAR (4 digits)
// "-" means the separator will be a hyphen
// So if, for example, you want to change the output date format to DD/MM/YYYY, change the above line of code to:
// date1 = StringSubstr(date1,8,2) + "/" + StringSubstr(date1,5,2) + "/" + StringSubstr(date1,0,4);
string time1 = TimeToStr(iTime(ccy,tf,i),TIME_MINUTES);
FileWrite(handle, date1, time1, iOpen(ccy,tf,i), iLow(ccy,tf,i), iHigh(ccy,tf,i), iClose(ccy,tf,i), iVolume(ccy,tf,i),iRSI(ccy,tf,14,PRICE_CLOSE,i), iAC(ccy,tf,i), iAD(ccy,tf,i),iADX(ccy,tf,14,PRICE_CLOSE,MODE_MAIN,i),iAlligator(ccy,tf,13,8,8,5,5,3,MODE_SMMA,PRICE_MEDIAN,MODE_GATORJAW,i), iAO(ccy,tf,i), iATR(ccy,tf,14,i), iBearsPower(ccy,tf,13,PRICE_CLOSE,i), iBands(ccy,tf,34,2,0,PRICE_CLOSE,MODE_LOWER,i), iBullsPower(ccy,tf,13,PRICE_CLOSE,i),iCCI(ccy,tf,14,PRICE_TYPICAL,i),iDeMarker(ccy,tf,14,i), iEnvelopes(ccy,tf,14,MODE_SMA,10,PRICE_CLOSE,0.10,MODE_UPPER,i),iForce(ccy,tf,13,MODE_SMA,PRICE_CLOSE,i),iFractals(ccy,tf,MODE_UPPER,i),iGator(ccy,tf,13,8,8,5,5,3,MODE_SMMA,PRICE_MEDIAN,MODE_UPPER,i),iIchimoku(ccy,tf,9,26,52,MODE_TENKANSEN,i),iBWMFI(ccy,tf,i),iMomentum(ccy,tf,14,PRICE_CLOSE,i), iMFI(ccy,tf,14,i), iMA(ccy,tf,13,8,MODE_SMMA,PRICE_MEDIAN,i), iOsMA(ccy,tf,12,26,9,PRICE_CLOSE,i), iMACD(ccy,tf,12,26,9,PRICE_CLOSE,MODE_MAIN,i),iOBV(ccy,tf,PRICE_CLOSE,i), iSAR(ccy,tf,0.02,0.2,i), iRVI(ccy,tf,10,MODE_MAIN,i), iStdDev(ccy,tf,10,0,MODE_EMA,PRICE_CLOSE,i), iStochastic(ccy,tf,5,3,3,MODE_SMA,0,MODE_MAIN,i), iWPR(ccy,tf,14,i), iCustom(ccy,tf,"Vortex_Indicator",14,1,i),iCustom(ccy,tf,"Vortex_Indicator",14,0,i),iCCI(ccy,tf,13,PRICE_TYPICAL,i),iCCI(ccy,tf,12,PRICE_TYPICAL,i),iCCI(ccy,tf,11,PRICE_TYPICAL,i),iCCI(ccy,tf,10,PRICE_TYPICAL,i),iCCI(ccy,tf,9,PRICE_TYPICAL,i),iCCI(ccy,tf,8,PRICE_TYPICAL,i),iCCI(ccy,tf,7,PRICE_TYPICAL,i),iCCI(ccy,tf,6,PRICE_TYPICAL,i),iCCI(ccy,tf,5,PRICE_TYPICAL,i),iCCI(ccy,tf,4,PRICE_TYPICAL,i),iCCI(ccy,tf,3,PRICE_TYPICAL,i),iCCI(ccy,tf,15,PRICE_TYPICAL,i), iCCI(ccy,tf,16,PRICE_TYPICAL,i),iCCI(ccy,tf,17,PRICE_TYPICAL,i),iCCI(ccy,tf,18,PRICE_TYPICAL,i),iCCI(ccy,tf,19,PRICE_TYPICAL,i),iCCI(ccy,tf,20,PRICE_TYPICAL,i),iCCI(ccy,tf,21,PRICE_TYPICAL,i),iCCI(ccy,tf,22,PRICE_TYPICAL,i),iCCI(ccy,tf,24,PRICE_TYPICAL,i),iCCI(ccy,tf,25,PRICE_TYPICAL,i),iCCI(ccy,tf,26,PRICE_TYPICAL,i),iStochastic(ccy,tf,1,3,3,MODE_SMA,0,MODE_MAIN,i));
// The above line writes the data to the file in the order: date, time, open, low, high, close, volume. Change the order to suit, if necessary
}
FileClose(handle);
LastActiontime=Time[0];
Comment("History output complete"); // Display a comment in the upper left corner of the chart to advise that process is complete
}
//----
return(0);
}
As you can see, I have a "Filewrite" near the bottom with different parameters. However, these are just for USDJPY. I would like to write to the same csv file with the same 63 parameters but multiple times for multiple currency pairs such as AUDUSD as shown in the code below.
The code below is what I want to do but doesnt work.
#property copyright ""
#property link ""
#property version "1.00"
#property strict
datetime LastActiontime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{ start("USDJPY",60); // This will produce daily history for GBPUSD
return(0);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
int start( string ccy, int tf )
{
string fname = ccy + "," + tf + ".csv"; // Same folder for each TF (...\experts\files)
int handle = FileOpen( fname, FILE_CSV|FILE_WRITE, "," ); // "," means that output data will be separated by commas; change if necessary
if ( LastActiontime != Time[0] && handle > 0 )
{
FileWrite( handle, // This writes the Header record to the file (change or remove to suit)
"Date,Time,Open,Low,High,Close,Volume,RSI,AC,AD,ADX,Alligator,AO,ATR,BearsPower,Bands,BullsPower,CCI,DeMarker,Envelopes,Force,Fractals,Gator,Ichimoku,BWMFI,Momentum,MFI,MA,OsMA,MACD,OBV,SAR,RVI,StdDev,Stochastic,WPR,Vortex_minus,Vortex_positive,CCI13,CCI12,CCI11,CC10,CCI9,CCI8,CCI7,CCI6,CCI5,CCI4,CCI3,CCI15,CCI16,CCI17,CCI18,CCI19,CCI20,CCI21,CCI22,CCI24,CCI25,CCI26,sstoch,Open,Low,High,Close,Volume,RSI,AC,AD,ADX,Alligator,AO,ATR,BearsPower,Bands,BullsPower,CCI,DeMarker,Envelopes,Force,Fractals,Gator,Ichimoku,BWMFI,Momentum,MFI,MA,OsMA,MACD,OBV,SAR,RVI,StdDev,Stochastic,WPR,Vortex_minus,Vortex_positive,CCI13,CCI12,CCI11,CC10,CCI9,CCI8,CCI7,CCI6,CCI5,CCI4,CCI3,CCI15,CCI16,CCI17,CCI18,CCI19,CCI20,CCI21,CCI22,CCI24,CCI25,CCI26,sstoch"
);
// for ( int i = 0; i < iBars( ccy, tf ); i++ ) // Use descending date sequence
for ( int i = iBars( ccy, tf ) - 1; i >= 0; i-- ) // Use ascending date sequence
{
string date1 = TimeToStr( iTime( ccy, tf, i ), TIME_DATE );
date1 = StringSubstr( date1, 5, 2 ) + "-"
+ StringSubstr( date1, 8, 2 ) + "-"
+ StringSubstr( date1, 0, 4 );
// NOTE: StringSubstr(date1,5,2) is the MONTH
// StringSubstr(date1,8,2) is the DAY
// StringSubstr(date1,0,4) is the YEAR (4 digits)
// "-" means the separator will be a hyphen
// So if, for example, you want to change the output date format to DD/MM/YYYY, change the above line of code to:
// date1 = StringSubstr(date1,8,2) + "/" + StringSubstr(date1,5,2) + "/" + StringSubstr(date1,0,4);
string time1 = TimeToStr( iTime( ccy, tf, i ), TIME_MINUTES );
FileWrite( handle,
date1, time1,
iOpen( ccy, tf, i ),
iLow( ccy, tf, i ),
iHigh( ccy, tf, i ),
iClose( ccy, tf, i ),
iVolume( ccy, tf, i ),
iRSI( ccy, tf, 14, PRICE_CLOSE, i ),
iAC( ccy, tf, i ),
iAD( ccy, tf, i ),
iADX( ccy, tf, 14, PRICE_CLOSE, MODE_MAIN, i ),
iAlligator( ccy, tf, 13, 8, 8, 5, 5, 3, MODE_SMMA, PRICE_MEDIAN, MODE_GATORJAW, i ),
iAO( ccy, tf, i ),
iATR( ccy, tf, 14, i ),
iBearsPower( ccy, tf, 13, PRICE_CLOSE, i ),
iBands( ccy, tf, 34, 2, 0, PRICE_CLOSE, MODE_LOWER, i ),
iBullsPower( ccy, tf, 13, PRICE_CLOSE, i ),
iCCI( ccy, tf, 14, PRICE_TYPICAL, i ),
iDeMarker( ccy, tf, 14, i ),
iEnvelopes(ccy,tf,14,MODE_SMA,10,PRICE_CLOSE,0.10,MODE_UPPER,i),iForce(ccy,tf,13,MODE_SMA,PRICE_CLOSE,i),iFractals(ccy,tf,MODE_UPPER,i),iGator(ccy,tf,13,8,8,5,5,3,MODE_SMMA,PRICE_MEDIAN,MODE_UPPER,i),iIchimoku(ccy,tf,9,26,52,MODE_TENKANSEN,i),iBWMFI(ccy,tf,i),iMomentum(ccy,tf,14,PRICE_CLOSE,i), iMFI(ccy,tf,14,i), iMA(ccy,tf,13,8,MODE_SMMA,PRICE_MEDIAN,i), iOsMA(ccy,tf,12,26,9,PRICE_CLOSE,i), iMACD(ccy,tf,12,26,9,PRICE_CLOSE,MODE_MAIN,i),iOBV(ccy,tf,PRICE_CLOSE,i), iSAR(ccy,tf,0.02,0.2,i), iRVI(ccy,tf,10,MODE_MAIN,i), iStdDev(ccy,tf,10,0,MODE_EMA,PRICE_CLOSE,i), iStochastic(ccy,tf,5,3,3,MODE_SMA,0,MODE_MAIN,i), iWPR(ccy,tf,14,i), iCustom(ccy,tf,"Vortex_Indicator",14,1,i),iCustom(ccy,tf,"Vortex_Indicator",14,0,i),iCCI(ccy,tf,13,PRICE_TYPICAL,i),iCCI(ccy,tf,12,PRICE_TYPICAL,i),iCCI(ccy,tf,11,PRICE_TYPICAL,i),iCCI(ccy,tf,10,PRICE_TYPICAL,i),iCCI(ccy,tf,9,PRICE_TYPICAL,i),iCCI(ccy,tf,8,PRICE_TYPICAL,i),iCCI(ccy,tf,7,PRICE_TYPICAL,i),iCCI(ccy,tf,6,PRICE_TYPICAL,i),iCCI(ccy,tf,5,PRICE_TYPICAL,i),iCCI(ccy,tf,4,PRICE_TYPICAL,i),iCCI(ccy,tf,3,PRICE_TYPICAL,i),iCCI(ccy,tf,15,PRICE_TYPICAL,i), iCCI(ccy,tf,16,PRICE_TYPICAL,i),iCCI(ccy,tf,17,PRICE_TYPICAL,i),iCCI(ccy,tf,18,PRICE_TYPICAL,i),iCCI(ccy,tf,19,PRICE_TYPICAL,i),iCCI(ccy,tf,20,PRICE_TYPICAL,i),iCCI(ccy,tf,21,PRICE_TYPICAL,i),iCCI(ccy,tf,22,PRICE_TYPICAL,i),iCCI(ccy,tf,24,PRICE_TYPICAL,i),iCCI(ccy,tf,25,PRICE_TYPICAL,i),iCCI(ccy,tf,26,PRICE_TYPICAL,i),iStochastic(ccy,tf,1,3,3,MODE_SMA,0,MODE_MAIN,i), iOpen("AUDUSD",tf,i), iLow("AUDUSD",tf,i), iHigh("AUDUSD",tf,i), iClose("AUDUSD",tf,i), iVolume("AUDUSD",tf,i),iRSI("AUDUSD",tf,14,PRICE_CLOSE,i), iAC("AUDUSD",tf,i), iAD("AUDUSD",tf,i),iADX("AUDUSD",tf,14,PRICE_CLOSE,MODE_MAIN,i),iAlligator("AUDUSD",tf,13,8,8,5,5,3,MODE_SMMA,PRICE_MEDIAN,MODE_GATORJAW,i), iAO("AUDUSD",tf,i), iATR("AUDUSD",tf,14,i), iBearsPower("AUDUSD",tf,13,PRICE_CLOSE,i), iBands("AUDUSD",tf,34,2,0,PRICE_CLOSE,MODE_LOWER,i), iBullsPower("AUDUSD",tf,13,PRICE_CLOSE,i),iCCI("AUDUSD",tf,14,PRICE_TYPICAL,i),iDeMarker("AUDUSD",tf,14,i), iEnvelopes("AUDUSD",tf,14,MODE_SMA,10,PRICE_CLOSE,0.10,MODE_UPPER,i),iForce("AUDUSD",tf,13,MODE_SMA,PRICE_CLOSE,i),iFractals("AUDUSD",tf,MODE_UPPER,i),iGator("AUDUSD",tf,13,8,8,5,5,3,MODE_SMMA,PRICE_MEDIAN,MODE_UPPER,i),iIchimoku("AUDUSD",tf,9,26,52,MODE_TENKANSEN,i),iBWMFI("AUDUSD",tf,i),iMomentum("AUDUSD",tf,14,PRICE_CLOSE,i), iMFI("AUDUSD",tf,14,i), iMA("AUDUSD",tf,13,8,MODE_SMMA,PRICE_MEDIAN,i), iOsMA("AUDUSD",tf,12,26,9,PRICE_CLOSE,i), iMACD("AUDUSD",tf,12,26,9,PRICE_CLOSE,MODE_MAIN,i),iOBV("AUDUSD",tf,PRICE_CLOSE,i), iSAR("AUDUSD",tf,0.02,0.2,i), iRVI("AUDUSD",tf,10,MODE_MAIN,i), iStdDev("AUDUSD",tf,10,0,MODE_EMA,PRICE_CLOSE,i), iStochastic("AUDUSD",tf,5,3,3,MODE_SMA,0,MODE_MAIN,i), iWPR("AUDUSD",tf,14,i), iCustom("AUDUSD",tf,"Vortex_Indicator",14,1,i),iCustom("AUDUSD",tf,"Vortex_Indicator",14,0,i),iCCI("AUDUSD",tf,13,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,12,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,11,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,10,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,9,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,8,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,7,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,6,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,5,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,4,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,3,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,15,PRICE_TYPICAL,i), iCCI("AUDUSD",tf,16,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,17,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,18,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,19,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,20,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,21,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,22,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,24,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,25,PRICE_TYPICAL,i),iCCI("AUDUSD",tf,26,PRICE_TYPICAL,i),iStochastic("AUDUSD",tf,1,3,3,MODE_SMA,0,MODE_MAIN,i),
);
// The above line writes the data to the file in the order: date, time, open, low, high, close, volume. Change the order to suit, if necessary
}
FileClose(handle);
LastActiontime=Time[0];
Comment("History output complete"); // Display a comment in the upper left corner of the chart to advise that process is complete
}
//----
return(0);
}
Step 0: Space-X "Just Read the Instructions" has some value:
The MQL4 code-execution environment has several specific forms of code. You have chosen the second least-feasible and 've hacked the specific-purpose OnInit(){...} handler, so as to do the job you need via an immediate call to start( str, int ).
The appropriate step to do this is to use an MQL4-script, where a plain start-stop sequence of operation does not destabilise other MetaTrader 4 Terminal real-time execution tuned facilites.
Script is a program intended for a single execution of some actions. Unlike Expert Advisors, scripts do not process any actions, except for the start event ( this requires the OnStart(){...} handler function in a script ). Scripts are stored in terminal_directory\MQL4\Scripts
Next: The "Just Read the Instructions" principle will show:
FileWriteParameters
file_handle
[in] File descriptor returned by FileOpen().
...
[in] The list of parameters separated by commas, to write to the file. The number of written parameters can be up to 63.
Solution: Again, "Just Read the Instructions" is well enough:
StringFormat will not work either:
Total number of parameters can't exceed 64 including the format string.
Your way is to ( yes, read the documentation :o) and ... ) use a trivial composition step:
StringConcatenate( a, // 1.
b, // 2.
c,
..
zz // 63.
);
Once I needed to have more parameters assembled, so 've used:
StringConcatenate( StringConcatenate( a_1, b_1, c_1, ..., zz_1 ),
StringConcatenate( a_2, b_2, c_2, ..., zz_2 ),
StringConcatenate( a_3, b_3, c_3, ..., zz_3 ),
...
StringConcatenate( a63, b63, c63, ..., zz63 )
);
Deeper nesting still possible, so 63*63*63 ... *63 may grow, until the RAM remains to suffice.
Epilogue:
It should be also noted, that initialising an MQL4-Script on a GBPUSD-graph will make accessible the GBPUSD-section of the MetaTrader4 Terminal. More care is needed, if one wants to read the graph-non-local currency TOHLCV-records, the more, if the MetaTrader4 Terminal [ History Centre ] has not yet such records collected from some previous interactions with the MetaTrader4 Server-side repository.
string template = "%s, %.5f, %.5f"; //add as much parameters here as you need
string toWrite = StringFormat(template,TimeToStr(Time[i]),Open[i],Close[i]);
FileWrite(handle,toWrite);

Plotting a function as a function of another function in Mathematica

I wasn't entirely sure what to search for, so if this question has been asked before, I apologize in advance:
I have two functions
R := Rref*mx(mx^(4/3) - C0)^(-1)
M := Mref*(mx + C1*mx^(-1)*((1 - C0*mx^(-4/3))^(-3) - 1))
where Rref, Mref, C0 and C1 are constants and mx is the variable. I need to plot R as a function of M. Surely there must be something available in Mathematica to do such a plot - I just can't seem to find it.
The comment is correct, in that what you have is a set of two "parametric equations". You would use the ParametricPlot command. However, the syntax of functions with parameters is sometimes tricky, so let me give you my best recommendation:
R[Rref_, C0_, C1_][mx_] = Rref*mx (mx^(4/3) - C0)^(-1);
M[Mref_, C0_, C1_][mx_] = Mref*(mx + C1*mx^(-1)*((1 - C0*mx^(-4/3))^(-3) - 1));
I like that notation better because you can do things like derivatives:
R[Rref,C0,C1]'[mx]
(* Output: -((4 mx^(4/3) Rref)/(3 (-C0 + mx^(4/3))^2)) + Rref/(-C0 + mx^(4/3)) *)
Then you just plot the functions parametrically:
ParametricPlot[
{R[0.6, 0.3, 0.25][mx], M[0.2, 0.3, 0.25][mx]},
{mx, -10, 10},
PlotRange -> {{-10, 10}, {-10, 10}}
]
You can box this up in a Manipulate command to play with the parameters:
Manipulate[
ParametricPlot[
{R[Rref, C0, C1][mx], M[Mref, C0, C1][mx]},
{mx, -mmax, mmax},
PlotRange -> {{-10, 10}, {-10, 10}}
],
{Rref, 0, 1},
{Mref, 0, 1},
{C0, 0, 1},
{C1, 0, 1},
{mmax, 1, 10}
]
That should do it, I think.

How to convert an 8-bit integer into a binary string in xquery?

At work today, we threw together this attempt:
xquery version "1.0";
declare option saxon:output "omit-xml-declaration=yes";
declare variable $x := 99;
string-join(
for $b in (128,64,32,16,8,4,2,1)
let $xm := $x mod ($b*2)
return
if ( $xm >= $b ) then "1" else "0"
, "")
Do you have a better way?
Taking Oliver's answer, I have made the reverse function.
declare function local:bin-byte($x as xs:string) as xs:unsignedByte
{
let $binary-nibbles := ("0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111")
return xs:unsignedByte(
(index-of( $binary-nibbles, substring($x,1,4) )-1) * 16
+ (index-of( $binary-nibbles, substring($x,5,4) )-1)
)
};
As a minor note, if you are returning text, not XML then you are probably better off setting method=text rather than omit-xml-declaration=yes, although in this case it makes no difference.
An alternative solution is using a lookup table:
declare function local:binary($x as xs:unsignedByte) as xs:string
{
let $binary-nibbles := ("0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111")
return concat($binary-nibbles[$x idiv 16 + 1],
$binary-nibbles[$x mod 16 + 1])
};
The most efficient way I can think of doing the reverse (at least in XQSharp) is:
declare function local:binary-string-to-integer($binary as xs:string)
as xs:integer
{
local:binary-codepoints-to-integer(string-to-codepoints($binary), 1, 0)
};
declare function local:binary-codepoints-to-integer(
$codepoints as xs:integer*,
$current-index as xs:integer,
$result as xs:integer)
as xs:integer
{
let $current-codepoint := $codepoints[$current-index]
return
if (empty($current-codepoint))
then $result
else local:binary-codepoints-to-integer(
$codepoints,
$current-index + 1,
2 * $result + $current-codepoint - string-to-codepoints("0"))
};
A quick performance test shows both methods to perform about the same when the query is interpreted, but this method is about 50% faster when the query is compiled. The recursive function method also has the benefit of not being limited to unsigned bytes.
Either way the runtime is about 10 microseconds so is nothing to be concerned about.
Recursive functions are clear if slower:
declare function local:decimal-to-binary ($d as xs:integer) as xs:string {
if ($d > 0)
then concat(local:decimal-to-binary(floor($d div 2)),$d mod 2)
else ""
};
eg
local:decimal-to-binary(42)
with inverse:
declare function local:binary-to-decimal($b as xs:string) as xs:integer {
if ($b ne "")
then local:binary-to-decimal(substring($b, 1, string-length($b)- 1)) * 2
+ number(substring ($b, string-length($b),1))
else 0
};
local:binary-to-decimal(local:decimal-to-binary(42))