Sum of ALL the digits of a Candle's High,Both INT and FRAC

Hi,
I have attempted to write an AFL to sum all the digits in a candle’s High.
I have beaten about the bush.Is there any better way or Syntax?
I have given the code what i have attempted so far.
This Code is meant for 4 Digit INTEGER price.
I am looking for alternate method which can solve any digit along with fraction,

inth1a=int(Ref(H,0)/1000);//first digit 

inth2=frac(Ref(H,0)/1000)*10;//first split for second digit
inth2a=int(inth2);//second split for second digit

inth3=frac(Ref(H,0)/100)*10;//first split for third digit
inth3a=int(inth3);//secondsplit for third digit

inth4=round(Ref(H,0));//Rounding the high value
inth41=frac(Ref(inth4,0)/10);//first split for Fourth Digit
inth4a=round(inth41*10);//Second split for fourth digit

Sumhighs=inth1a+inth2a+inth3a+inth4a;//first addition of all the digits.
Highs1=IIf(Sumhighs<10,Sumhighs,int((Sumhighs)/10)+frac((Sumhighs)/10)*10);
Highs2=IIf(sumHighs<10,sumhighs,IIf(Highs1<10,Highs1,int(Highs1)/10+frac(Highs1)/10)*10);
Highs3=IIf(Highs2<10,Highs2,int(Highs2)/10+frac(Highs2)/10);
Highs4=IIf(Highs3<10,Highs3,int(Highs3)+frac(Highs3));

Any help would be appreciated.

Thanks,
Gloria Filamino,

Hello Gloria,

I wonder why do you need the sum of all digits of a certain number? I would be really surprised if it's useful to predict the future price behaviour, but maybe I'm wrong ... :wink:

Anyway, you can try my code below. There's an alternative way (probably easier) of extracting digits from any number - by converting it to a string. For example:

EnableTextOutput( False );
Version( 5.90 );

Number = 12500.16; // An example number
printf( "\nNumber  =  " + Number + "\n" );

NumberStr = NumToStr( Number, 1.2, False, True );
NumberStr = StrReplace( NumberStr, ".", "" );
NumberStrLen = StrLen( NumberStr );
DigitsSum = 0;

for( i = 1; i <= NumberStrLen; i++ )

{
    DigitStr = StrLeft( NumberStr, 1 );
    Digit = StrToNum( DigitStr );
    DigitsSum += Digit;
    NumberStr = StrMid( NumberStr, 1 );
    printf( "\nDigit  " + i + "  ---->  " + Digit );
}

printf( "\n\nDigits' sum =  " + DigitsSum );

Sum of digits

... it gives you the sum of all digits of a certain number. I didn't have much time to check this code thoroughly, but it should work properly.

Regards

2 Likes

I too do not understand why you want to add digits… Anyway here is another code snippet to get the sum of all the digits reduced to a single digit.
I’m using a sample value to easily follow the code with the debugger to understand how it works.
(I split the integer and decimal parts, reduce them to a single digit, sum them and reduce again).

// This function reduce any integer number to a single digit 
function reduce( n )
{
    n = abs( n );
    while( n >= 10 )
    {
        n = ( n % 10 ) + int( n / 10 );
    }
    return n;
}

// Let's use a sample value
value = 987.65; // 9+8+7= 24 . 6+5 = 11 -> 2+4 = 6 . 1+1 = 2 -> 6+2 = 8
integerPart  = int( value );
decimalsPart = int( frac( value ) * 100 ); // in this case it works with 2 decimals
singleDigit  = reduce( reduce( integerPart ) + reduce( decimalsPart ) );

If this is what you were looking for, it will not be too difficult to adapt this logic to your arrays.

1 Like

Adding digits is a “numerology”.

2 Likes

Yes , Absolutely Correct.
Thanks
Gloria Filamino

Error

Thanks for your effort.I am using the function for the first time.I have never used before,I got some clues from your code.

in the attached image it shows some error in WHILE statement.

Thanks,
Gloria Filamino.

A little simplified version (which also doesn't require AB 5.90). Of course you can get rid of all printf() and EnableTextOutput() lines :

EnableTextOutput( False );
Number = 32107.51; // An example number
printf( "\nNumber  =  " + Number + "\n" );
NumberStr = NumToStr( Number, 1.2, False, True );
NumberStr = StrReplace( NumberStr, ".", "" );
NumberStrLen = StrLen( NumberStr );
DigitsSum = 0;

for( i = 1; i <= NumberStrLen; i++ )

{
    DigitStr = StrMid( NumberStr, i - 1, 1 );
    Digit = StrToNum( DigitStr );
    DigitsSum += Digit;
    printf( "\nDigit  " + i + "  ---->  " + Digit );
}

printf( "\n\nDigits' sum =  " + DigitsSum );

Sum of digits

1 Like

Gloria, the error message is very clear.
You are passing an array to a function that expects a Numeric.

In order to use it, as suggested by the same error message, you must invoke the function passing as a parameter a bar value (in your case of the H array) using the [] (array subscript operator).

The easiest way (but probably not the best one....) is to use a loop over the bars.

Here is same sample code.

function reduce( n )
{
    n = abs( n );
    while( n >= 10 )
    {
        n = ( n % 10 ) + int( n / 10 );
    }
    return n;
}

// Used to test the performance - with lot of bars this could be slow...
GetPerformanceCounter(True); // reset counter to zero

hInteger = Int(H);
hDecimals = Int( frac( H ) * 100 ); // in this case it works with 2 decimals
for (i = 0; i < BarCount; i++) {
	// numerology[i]  = reduce(reduce(HInteger[i]) + reduce(HDecimals[i]));
	
	// the line above will be enough but for the following exploration 
	// we will store and use some intermediate steps/arrays 
	reducedHInteger[i] = reduce(hInteger[i]);
	reducedHDecimals[i] = reduce(hDecimals[i]);
	numerology[i] = reduce(reducedHInteger[i] + reducedHDecimals[i]);
	
}	

elapsed=GetPerformanceCounter();
_TRACE("Bar count = " + WriteVal(BarCount, 1.0) + " - Processed in " + WriteVal(elapsed, 1.0) + " milliseconds.");

// Exploration - use the current symbol
Filter = 1;
AddColumn(H, "High");
AddColumn(hInteger, "Integer of H");
AddColumn(hDecimals, "Decimals of H");
AddColumn(reducedHInteger, "Reduced of Integer");
AddColumn(reducedHDecimals, "Reduced of Decimals");
AddColumn(numerology, "Numerology sum");

Plot(numerology, "Numerology", colorYellow, styleHistogram | styleThick);

I also added some exploration lines so you can better understand what happens (use a single symbol in the exploration, i.e the current one).

The Plot line at the end of the script, using SPY (EOD), gave me this chart (lower pane).

immagine

The upper pane formula is just:

Plot(H, "High", colorDefault, styleStaircase );
3 Likes

@beppe, could you tell me, what is the philosophy behind “reducing all digits to a single digit” in your example? Is your code above only a partial solution (an unfinished example of extracting the digits one by one)? Or maybe a finished one - having something to do with “numerology”? The results which it brings don’t equal the sum of all the digits of particular numbers - which was Gloria’s initial request…

@Gloriafilamino, just out of curiosity, could you explain to me (I’ve always been very interested in astronomy, but not at all in astrology or numerology :wink: ) in what situations do you expect such approach to market data to be useful?

Thank you both in advance :slight_smile:

1 Like

Milosz,
my code is just an example. I tried to understand what Gloria was looking for (maybe I’m totally wrong!).
I provided a possible solution to recursively adding the digits of a number (and then used it applying it to a price series).

The logic of my code is to get a single digit like if I was adding all the digits together until it gets down to a single digit (as said above, actually, this may not be what Gloria wanted…, but the last part of her code seemed to reduce the numbers to single digits)

// 3+2+1+0+7 = 13 -> 1+3 = 4  (Integer part)
// 5+1 = 6 (decimals part)
// 4+6 = 10 -> 1+0 = 1 (my final result is a single digit under 10)
// Your result is 19 - if you add 1+9 you get 10 then again 1+0 = 1

But you are right, my code sometimes DOES NOT WORK as expected since the line:

decimalsPart = int( frac( value ) * 100 ); 

may produce an integer different from what I expected! (At least it happens on my machine using Amibroker 6.10 … I have not yet upgraded to latest version).
Using your sample number (32107.51) for the decimals part, instead of 51, in the debugger, I get 50 (and then the end result is wrong),

I imagine this is related to some rounding error in my usage of frac (it would be nice if you or Tomasz, or anyone else, could help me to figure out how to avoid it, if it is not due to an old version of AB) .

Anyway, since using the NumToStr, like you did, seems to work better, it maybe used instead of my procedure to get the fractional part as an integer as per this line of code:

decimalsPart = StrToNum(StrExtract(NumToStr(value, 1.2), 1, '.')); // 2 decimals

In conclusion, all of this is nothing more than a sample: personally, I do not see any useful application of it to actual trading! (I do not trust in numerology).

I only used the word “numerology” in the second sample code since TJ suggested that adding up digits was probably related to it (initially I wondered about the purpose of adding up the digits).

Milosz, thanks for your feedback.

3 Likes

Giuseppe, thank you for the information.

Usually in AFL (and in programming in general - you know it better than me :wink: ) one thing can be achieved in many ways. Which one is better (or the best) depends on many different factors. In this case if I needed to sum digits of only some selected numbers, I would probably choose my solution (because it is simple and automatically adjusts to a number of any length and it works with or without the decimal part), but if I needed to sum the digits of every single candle, I would seek an array based solution. I am almost sure that 100% array-based solution can be coded, but in this case it would need to take into account the changing lenght of the integer and decimal part.

I think that (as you suggested) it is because of some differences in rounding methods, but I’m not 100% sure.

Regards

1 Like

Milosz & Beppe,

I thank both of you for showing interest to help me out.
Title is bit misleading thus caused confusion, reducing all digits to single digit was actual requirement.
I just want to combine it with Specific scrip’s Natal chart and it is more of Astrology than Numerology.

Lot of work has yet to be done to finalize if it is really worth to put into trade.
I just want to limit this subject here as i am aware that this forum is meant for Amibroker and AFL.
I am open to share more about it to if come through personal mail.

Finally thanks again to everyone who participated in this thread.

Gloria Filamino

2 Likes

Gloria

Year ago, i had a friend and i have to write few stupid (for me) afl for her. I remember siting both of us on the desk, and she was describe me all this angles between the moon, earth, stars, was amazing how she remember all this kind of thinks, that I canot put in my head. But was fun.

As i see you interest about astrology i bet you didn’t miss the the free Amibroker Add On SkyQuant?

Keep going

pl share your any further effert on this AFL i have made an optimizer out of it pl share yr email id mine is deepakjosh71@gmail.com

If you made optimizer out code from here why don't you post it here for the benefit of community ? Please do post here

1 Like

Sir
i am from India. dont have any coding background,just did mix n match, pl chk d below code if it help to community
pl update me if i go wrong Thx for yr mail

function reduce( n )
{
    n = abs( n );
    while( n >= 10 )
    {
        n = ( n % 10 ) + int( n / 10 );
    }
    return n;
}

// Used to test the performance - with lot of bars this could be slow...
GetPerformanceCounter(True); // reset counter to zero

hInteger = Int(H);
hDecimals = Int( frac( H ) * 100 ); // in this case it works with 2 decimals
for (i = 0; i < BarCount; i++) {
	// numerology[i]  = reduce(reduce(HInteger[i]) + reduce(HDecimals[i]));
	
	// the line above will be enough but for the following exploration 
	// we will store and use some intermediate steps/arrays 
	reducedHInteger[i] = reduce(hInteger[i]);
	reducedHDecimals[i] = reduce(hDecimals[i]);
	numerology[i] = reduce(reducedHInteger[i] + reducedHDecimals[i]);
	
}	

elapsed=GetPerformanceCounter();
_TRACE("Bar count = " + WriteVal(BarCount, 1.0) + " - Processed in " + WriteVal(elapsed, 1.0) + " milliseconds.");

// Exploration - use the current symbol
Filter = 1;
AddColumn(H, "High");
AddColumn(hInteger, "Integer of H");
AddColumn(hDecimals, "Decimals of H");
AddColumn(reducedHInteger, "Reduced of Integer");
AddColumn(reducedHDecimals, "Reduced of Decimals");
AddColumn(numerology, "Numerology sum");

Plot(numerology, "Numerology", colorYellow, styleHistogram | styleThick);


Plot(numerology, "Numerology", colorYellow, styleHistogram | styleThick);

function ParamOptimize( description, defaultVal, minv, maxv, step )
{
    return Optimize( description, Param( description, defaultVal, minv, maxv, step ), minv, maxv, step );
}

function ChkNUM(P)
{
global PatternName;
if(P == 1)  { PatternName = "1"; Pv = (numerology==1); }
else if(P == 2) { PatternName = "2"; Pv = (numerology==2); }
else if(P == 3) { PatternName = "3"; Pv = (numerology==3); }
else if(P == 4) { PatternName = "4"; Pv = (numerology==4); }
else if(P == 5) { PatternName = "5"; Pv = (numerology==5); }
else if(P == 6) { PatternName = "6"; Pv = (numerology==6); }
else if(P == 7) { PatternName = "7"; Pv = (numerology==7); }
else if(P == 8) { PatternName = "8"; Pv = (numerology==8); }
else if(P == 9) { PatternName = "9"; Pv = (numerology==9); }

return Pv;
}
  
  
  
   P = ParamOptimize("ChkNUM",1,1,9,1);
  NUMCHK = ChkNUM(P); 
  
  
  BYUCANDLEFIX =Ref (NUMCHK,-1) ;

Buy = BYUCANDLEFIX ;

Sell = BarsSince (Buy )==0; ;

Buy = ExRem( Buy, Sell );
Sell = ExRem( Sell, Buy );


BuyPrice = ValueWhen( Buy, O );
SellPrice = ValueWhen( Sell, C  );

PlotShapes(shapeUpArrow*Buy,colorBrightGreen);
PlotShapes(shapeDownArrow*Sell,colorRed);
PlotShapes(IIf(Buy , shapeStar, shapeNone),colorGold, 0, L, Offset=-65);
PlotShapes(IIf(Sell, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, High, Offset = -15 );
PlotShapes( IIf( Buy, shapeUpArrow , shapeNone ), colorBrightGreen, 0, Low, Offset = -15 );

Good for you to share the code, but you seriously need to check the Plot() functions.
They are pretty resource demanding functions compared to others and even though AB is super fast, its not a good idea calling them repeatedly.

Plot(numerology, "Numerology", colorYellow, styleHistogram | styleThick);
This line appears twice.

Also, this block

PlotShapes(shapeUpArrow*Buy,colorBrightGreen);
PlotShapes(shapeDownArrow*Sell,colorRed);
PlotShapes(IIf(Buy , shapeStar, shapeNone),colorGold, 0, L, Offset=-65);
PlotShapes(IIf(Sell, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, High, Offset = -15 );
PlotShapes( IIf( Buy, shapeUpArrow , shapeNone ), colorBrightGreen, 0, Low, Offset = -15 );

has redundant same calls for shapeDownArrow and shapeUpArrow
they can all, be replaced by one plot call.
Ofcourse, you will loose the star and square, else you can write another common one for them in another plot.

shape1 = Buy * shapeUpArrow + Sell * shapeDownArrow;
PlotShapes( shape1, IIf( Buy, colorBrightGreen, colorRed ), 0, IIf( Buy, Low, High ), -15 );

In this code, you might not see sell signals, because you have same bar exit and ExRem but same bar exit isn't logical until you can define exactly when and how the entry and exits actually occur.

Also, if you wanted to scale down the Yellow Numerology bars, then you can add, 5X to min. Its a hack but it does work :slight_smile: technically your min max should be to scale values.
like this

Plot( numerology, "Numerology", colorYellow, styleHistogram | styleOwnScale, 7); // 5 or 7, 5 is 20%

So, I have Sell = 1; so I sell next bar since its not logically known,
and you can have something like this:

image

In non-optimize mode, optimize returns the default. In your case its Number 1

So in this case, all buys appear on the next bar after a 1 count occurs, and sell=1, as in sell next bar or something that you define.

And you can comment out Performance Counter and Trace in production :stuck_out_tongue:

2 Likes
n = abs( n );

The above line can be dropped and another line be replaced by

hInteger = Int( abs( H ));
// This line can also be written like this
hInteger = abs( H ) | 0;

We call abs() only once for the whole array, instead of calling it i iteration number of times.

1 Like

Exploiting side effects of bit-wise operators (implicit cast to integer done by bitwise or) is not good for code clarity and does not bring any speed benefits.

1 Like

ok noted, has come up a few times in the recent weeks :slight_smile: We can stick with Int() function.

1 Like