Should I leave temporarily AFL?

Hi guys,

I am struggling with AFL and I is been harder than I expected. It is not by AFL but me. For everything I solve, I have new ten doubts. I'm sure Amibroker will allow me to do projects I want to develop, and I am absolutely decided to learn to programme with AFL. It's just about time.

I must accept that not only I have not array-wise thinking but I do not have computational thinking. I am not a quant or a programmer. I'm just a newbie, an absolute beginner to this.

Said this, I am wondering if maybe I was wrong trying to begin to programming directly with AFL (where I want to arrive) but it would be a better idea beginning with another easy language with more resources (courses, youtube videos, books, etc..). Reading in another post, I am considering to buy some "Head First" book ("Programming" or "Learning to code") and begin with Python to learn the basics of programming... always thinking in to come back as soon as I can to AFL (what I want). It is not learning Python itself but just getting a computational thinking. I know that the road will be longer but it may be the best.

What do you think? It is a good or a bad idea? In the long run, maybe I'll save time?

Thanks,

1 Like

AFL is much easier than Python (IMHO). And AFL is not PIA like Python (IMHO).

Just make a detailed example of what you are not understanding.
What exactly are you trying to achieve (code wise)?
And what is the exact road block preventing you from reaching that sample goal?

I mean you obviously have started to write some code, right?
Where are/were you stuck there?

2 Likes

@BernieTGN AmiBroker is a powerful technical analysis and trading system development software. As such it may take many years worth of study to master. But most worthwhile programming languages will also take in depth study to master.

The good news is that you do not initially need to use all of the available capabilities. Think of it like an onion, where you can slowly peel back the layers as you find out about new features that you need.

You also wrote that other programming languages may have more "courses, videos, books" to help you learn. That may be true but there are similar resources available for AmiBroker. Read through these forum threads for a long list of helpful resources, guides, books, videos, courses etc.

And you have this forum with many experienced users as well as the program's developer available to answer well thought out questions.

One important item that you have not mentioned, are you a knowledgeable investor/trader? If not, then perhaps you should make some progress in that field of study before you learn AmiBroker.

3 Likes

In general, on this forum if you come in and ask for AFL to do something specific, especially with a horrible description of the expectation, you'll get no where. If you come into the forum with an example of what you tried, where your stuck and a clear description of what you want to do, you'll get some good guidance.

I'm far from being a comprehensive AFL user, but the beautiful thing about Amibroker compared to say going with just some data and C# or Python is that I know when theirs a problem or things aren't lining up the way I expect, that my code is the issue and not the backtester/scanner. The amount of work that would be required for myself to write a backtester(a portfolio level backtester would be a nightmare for any novice) just is not feasible. It'd be a nightmare to make sure its running as you intend.

Programming is frustrating, you have to be precise and literal as the code will do exactly as its told. I can't remember who said this but imagine telling a kid to go use the washroom but they don't lift the toilet seat, computers require precise instructions.

I guess it may depend on your goals, myself I use Amibroker with a bit of Excel to combine some quantative with discretionary trading.

2 Likes

@fxshrat I have written some easy codes (to make probes) that run well. I usually work first with Exploration to see how these works and I am learning... but try and error continually. It is slower than expected. Maybe I am getting impatient...

With the last one, I just only pretend to tell to Amibroker to buy five days before EOM and sell at the close of EOM. I have been able to identify EOM day using the following code...

isEndOfMonth = TimeFrameExpand(1,inMonthly,expandPoint);

but I have not found the correct way to tell him to buy at five days prior open. I have tried different ways but I failed... and I guess it must be a silly thing. When I wrong, I analyze it and I find out what I have made wrong... realizing my lack of programming skills. That's the reson of my question.

One of my problems is that I can't tell Amibroker to buy five days before EOM, as I have told. I have an array indicating true when is EOM. I see in my exploration dateNum() of EOM days and that days less five (in numbers, no dates). But, when I try to code buying I fail because I am referring (in all probes) to an array with "true" or "false" indicating when EOM is. I mean, I am wrong telling to Amibroker to buy when "true" (1) less five (-4) in different ways, for example... and I haven't found the right way for buying five days before EOM. I am sure I will find how to do, but sometimes it is frustrating. But I insist. It is not AFL. I know, it is me.

@portfoliobuilder Thank you very much, especially for the second post. I didn't know it.

I am afraid it is easier to find more resources about other languages, but I knew it before purchasing Amibroker. For example, in Spanish there only are a few ones. High level is here, at the forum, but it is not about asking all the time...

Referring to my knowledge, it can always be improved. That is precisely why I want to learn AFL and using Amibroker (exploring and backtesting).

@Metamega I absolutely agree. I have experienced it with my last two topics, but it begins to be too many questions to ask in the forum, I'm afraid... and not about AFL itself but programming.

@BernieTGN: Your "five days until the end of the month" problem can be easily solved with the Ref() function. Assuming you are operating on daily bars, you can just do something like this:

isEntryDay = Ref(isEndOfMonth,5);

Learning to think like a programmer is easier for some people than for others, but like all things in life the more you practice the more proficient you will become. If you really want to start with another language, you should probably start with a derivative of the C language or JScript, as suggested in the post by @Tomasz and linked above by @portfoliobuilder. In the long run, I think it will probably be faster to just dive into AFL, implementing simple things first and working toward the more complex. Once you truly grasp the power of AmiBroker's array processing, everything else will begin to fall into place for you.

3 Likes

Did you try this: https://www.youtube.com/results?search_query=lets+learn+amibroker

For example this https://www.youtube.com/watch?v=HRCUyHJ-Sc4 is the most enthusiastic & happy coding lesson ever :slight_smile:

5 Likes

@mradtke I'm still crying with rage. :joy: Thanks a lot. That's what I meant. It's just what I wanted.
I have used that function repeatedly but, for whatever reason, it did not occur to me to do it that way. Lack of programming creativity, sure.

I'll do that way and will be more patient.

@Tomasz Yes, but probably I was wrong when I didn't begin with this guy. I mean, I have found quite resources for Amibroker (not in my mother tongue, unfortunately) but, choosing one way at the beginning, I did start with Bandy's books. And those are very good. I really happy with this author because I am learning a lot about trading systems but I hoped to learn more about AFL (or in a different way), too. For an absolute beginner to programming like me -from the point of view of programming- maybe another more structured way would have been better (you know... as "idiots guide to"). :slightly_smiling_face:

When I am referring to resources I am doing it that way. I have seen this guy site and a pair of videos and I absolutely agree with you. At first, I didn't want to change from one resource to other continually because sometimes it is a very bad decision. That's the reason why I chose Bandy's books. I think (by your opinions) it would be better for me to stop for a while and focus on AFL programming, not changing temporally of language. But I will stop with Bandy for a couple of weeks and begin to study this guy work. It seems a very good option (quite structured) and I understand a lot his pronunciation.

Thanks a lot!

This forum member offers some good advice. On first reading, they may sound like fairly minor steps. But when put into practice, those first two steps have made a huge difference for me.

3 Likes

As for 5th day before month end...
I don't know if some people are just theorists browsing historical data...

The line suggested above does not work in live trading if being at current actual bar in real time asking for "Is it 5th day before end of month?". The upper line requires existing "future" data.

And that line will also not work on last month e.g. if last month's last date would be Nov 10th then that day would be considered as last day of month and Nov 4th would be considered as 5th day before end of month. Obviously incorrect.

Besides at last month that line will mark all days after "5th day before EOM" with "TRUE" (1). Also note that that line will not include weekends. It will consider existing trading days only.

Another pitfall... if there are data holes then it will pick wrong date also e.g. if there is data hole from Nov 19th to Nov 26th it will pick Nov 19th as 5th day before months end. Obviously wrong again.

So @BernieTGN if you look for something that actually works (properly) on historical data as well as in realtime when actually trading live then you have to do different approach.

4 Likes

Hi @fxshrat, thank you very much for your post.

I understand what you say. I work in Exploration and I see results are not correct on last month, and nothing to ignore the other arguments. I think you are right.

I think I know how to solve the problem with EOM, but I have to think more about the 5th day before EOM.

I thought the road would be long but I see it will be longer... it will be a matter of enjoying it. :slightly_smiling_face: I'll go on working on this code.

Thanks!

Captura

My assumption was that the EOM problem was for back testing / historical analysis only. In live trading, you would obviously know whether today is five days before the end of the month or not... no need to have AmiBroker tell you that.

1 Like

@BernieTGN, below code is how I would approach this more realistically since it is about actual nth day before EOM and not about some day. It works in real-time/at last month of array as well as historically.
There are a few scenarios in there depending on what you actually need (so you need to study it a bit).
(Checking for holidays is not included! But that's doable also.)

function LastDOM( mth, yr ) {
	/// last day of month
	/// function returns datetime format
	/// works in realtime as well as historically
	/// mth, yr may be type array or number
	/// AFL function by fxshrat@gmail.com	
	local DIM, DIFeb, days;
	DIM = IIf( mth % 2 == 0 AND mth < 8 OR mth == 9 OR mth == 11, 30, 31 );	
	/// leap year approach from:
	/// @link https://stackoverflow.com/questions/3220163/how-to-find-leap-year-programatically-in-c
	DIFeb = IIf( (yr & 3) == 0 AND ((yr % 25) != 0 OR (yr & 15) == 0), 29, 28 );
	///	
	days = IIf(mth == 2, DIFeb, DIM);	
	result = DateTimeConvert( 2, 10000 * (yr-1900) + 100 * mth + days);
	return result;
}

function LastBOM( mth, yr ) {	
	/// last business day of month (not including holidays check)
	/// function returns datetime format
	/// works in realtime as well as historically
	/// mth, yr may be type array or number
	/// AFL function by fxshrat@gmail.com
	local ldm, last_dow;
	ldm	= LastDOM( mth, yr );
	last_dow = DateTimeConvert( 9, ldm );
	result = IIf( last_dow == 6, DateTimeAdd(ldm, -1, inDaily), // if last EOM is Saturday then get FRI dt
			 IIf( last_dow == 0, DateTimeAdd(ldm, -2, inDaily), // if last EOM is Sunday then get FRI dt
			 ldm ) );
	return result;
}

/// output 5th day before Month end
/// it does not check for holidays! But it is doable also
/// There are a few scenarios in there depending on what you actually need (so you need to study it a bit!)
/// @link https://forum.amibroker.com/t/should-i-leave-temporarily-afl/9587/13
dt = DateTime();
// Last day of month
EndOfMonth = LastDOM( Month(), Year() ); 
// OR: 
// use Last Business day of Month function 
// if you do not want to count from last day of month being on weekends
// then uncomment below line
//EndOfMonth = LastBOM( Month(), Year() );

// fifth day before end of month or before last business day of month
fifth_day = DateTimeAdd(EndOfMonth, -5, inDaily);
// OR additionally add (or comment) below two variables.
// If fifth day before EOM is on weekend and you want to get business day (FRI) before weekend 
fifh_dow = DateTimeConvert( 9, fifth_day );
fifth_day = IIf(fifh_dow == 6, DateTimeAdd(fifth_day, -1, inDaily), // if fifth_day is Saturday then get FRI dt
			IIf(fifh_dow == 0, DateTimeAdd(fifth_day, -2, inDaily), // if fifth_day is Sunday then get FRI dt
			fifth_day ) );
//
isEntryDay = ExRem(dt >= fifth_day, dt < fifth_day);
// or if you want equality check instead then uncomment below line
//isEntryDay = dt == fifth_day;

Plot(C, "Price", colorDefault, styleCandle );
Plot(isEntryDay, "", colorRed, styleHistogram | styleOwnScale | styleNoLabel);
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}} {{VALUES}}" ));

@mradtke, the line posted does not properly work historically as posted above. The task is not about some day but about nth day before EOM. And in live trading if you automate (I don't know but maybe BernieTGN wants to some day or at least does not want to check manually himself every month) then you obviously would need some (more) proper way to determine whether some day is the actual day or not "right now". Whether you need it or not doesn't matter.

7 Likes

@mradtke
At the moment, your assumption was correct. I have to learn a lot before going automated trading. @fxshrat has gone beyond and he is right. Both codes were improbable, especially -in my opinion- mine, because it doesn't return the correct EOM day if last month is not finished. It was a surprise for me because I got this code from Connor's Research and I did not think it could return an error date in some scenarios. This is a good lesson for me.

@fxshrat
Thank you very much for your code. I have to go away but I will study it as soon as I come back. I think I was much further from the solution than I thought...

Thanks!

@fxshrat Thank you very much for your help. I really appreciate it. I am learning a lot analyzing your code.

BTW thanks for providing that link. Leap year approach has given to me a lot of food for thought, especially because I was not well understanding expressions like "year & 3" or "year 15". That link has helped me a lot.

Now I am doing probes with Exploration to deeply understanding how it works. Controlling variable values when I make changes help me a lot.

Thanks a lot for your time!

1 Like

I would recommend Cesar Alvarez and his self paced courses .. For me personally well worth the money, IMO . -phil

@phil1424

Hi! Thanks for the information.

@BernieTGN,
FYI, my previously posted LastDOM function is only working on EOD data (if doing equality checks with DateTime() array -> Datetime() == YourDateTime ). (Update of LastDOM is below)

If you have iEOD data (-> intraday data or Daily TF constructed from intraday data) and you do such equality check with LastDOM() there then it will not work.

Why? Because if having EOD data then time info is missing while on the other hand if using iEOD data then you have time info (->e.g. "00:00:00" for all daily bars).

LastDOM has this line -> DateTimeConvert(2, dn) -> default 3rd (time) argument is Null. So if you compare e.g "2018-11-30" of DateTimeConvert with intraday datetime element such as "2018-11-30 00:00:00" then it will be false despite of day being the same one.

So with a trick one can check if it is EOD data or iEOD data using DateTimeConvert:

// if EOD data then it returns false (0) (daily TF is applied)
// if iEOD data then it returns true (1)
tn = TimeNum();
isIEOD = tn == DateTimeConvert(1, DateTime());
// on EOD data (daily bars data) below printf returns timenum 316363
printf( "TimeNum: %g",  SelectedValue(DateTimeConvert(1, DateTime())));
printf( "\nIs it iEOD? %s", StrExtract("No.,Yes.", SelectedValue(isIEOD)) );

So here is adjustment of LastDOM() function now working with EOD and iEOD data.
It is added Timenum() to DateTimeConvert if iEOD data and it is added Null if EOD data (if Daily TF is selected on latter one).
I have also added separate switches to Friday and Monday if Date is on weekend.

function LastDOM( mth, yr ) {
	/// last day of month function
	/// function returns datetime format
	/// works in realtime as well as historically
	/// mth, yr may be type array or number
	/// now works on EOD and iEOD data
	/// AFL function by fxshrat@gmail.com	
	local DIM, DIFeb, days, dn, tn;
	DIM = IIf( mth % 2 == 0 AND mth < 8 OR mth == 9 OR mth == 11, 30, 31 );	
	/// leap year approach from:
	/// @link https://stackoverflow.com/questions/3220163/how-to-find-leap-year-programatically-in-c
	DIFeb = IIf( (yr & 3) == 0 AND ((yr % 25) != 0 OR (yr & 15) == 0), 29, 28 );
	///	
	days = IIf(mth == 2, DIFeb, DIM);		
	dn = 10000 * (yr-1900) + 100 * mth + days;
	///
	tn = TimeNum();
	tn = IIf(tn == DateTimeConvert(1, DateTime()), tn, Null);
	return DateTimeConvert(2, dn, tn);
}

function switch_to_fri( dt ) {
	local dt, result;
	dow = DateTimeConvert( 9, dt );
	result = IIf( dow == 6, DateTimeAdd(dt, -1, inDaily), // if date is Saturday then get FRI dt
			 IIf( dow == 0, DateTimeAdd(dt, -2, inDaily), // if date is Sunday then get FRI dt
			 dt ) );// else get input date
	return result;
}

function switch_to_mon( dt ) {
	local dt, result;
	dow = DateTimeConvert( 9, dt );
	result = IIf( dow == 6, DateTimeAdd(dt, 2, inDaily), // if date is Saturday then get MON dt
			 IIf( dow == 0, DateTimeAdd(dt, 1, inDaily), // if date is Sunday then get MON dt
			 dt ) );// else get input date
	return result;
}

function LastBOM( mth, yr ) {	
	/// last business day of month (not including holidays check)
	/// function returns datetime format
	/// works in realtime as well as historically
	/// mth, yr may be type array or number
	/// AFL function by fxshrat@gmail.com
	local ldm, result;
	ldm	= LastDOM( mth, yr );
	result = switch_to_fri( ldm );
	return result;
}

/// output 5th day before Month end
/// it does not check for holidays! But it is doable also
/// There are a few scenarios in there depending on what you actually want (so you need to study it a bit!)
/// @link https://forum.amibroker.com/t/should-i-leave-temporarily-afl/9587/17
dt = DateTime();
// Last day of month
EndOfMonth = LastDOM(Month(), Year()); 
// OR: 
// use Last Business day of Month function 
// if you do not want to count from last day of month being on weekends
// then uncomment below line
//EndOfMonth = LastBOM( Month(), Year() );

// fifth day before end of month or before last business day of month
fifth_day = DateTimeAdd(EndOfMonth, -5, inDaily);
//
// OR additionally add (or comment) below variable.
// If fifth day before EOM is on weekend and you want to get business day (FRI) before weekend 
fifth_day = switch_to_fri( fifth_day );
//
// OR switch to Monday (COMMENT upper 'fifth_day' single line before uncommenting below one!)
//fifth_day = switch_to_mon( fifth_day );
//
isEntryDay = ExRem(dt >= fifth_day, dt < fifth_day);
// or if you want equality check instead then uncomment below line
//isEntryDay = dt == fifth_day;

Plot(C, "Price", colorDefault, styleCandle );
Plot(isEntryDay, "", colorRed, styleHistogram | styleOwnScale | styleNoLabel);
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}} {{VALUES}}" ));

7 Likes

@fxshrat

Thank you very much for your work. I have no words...

I am working with EOD data but I have a Symbol with IEOD data, and I have seen the first code works perfectly.

Taking a look at both switch functions, I have realized there is a thing that escaped to me with the other two functions, too. I had not worked with functions yet. I made a correct assumption, but I don't not why. It must be a simple thing so I will try to find the answer by myself first.

I insist, thanks a lot for your help. I am reading other posts of yours at the forum and I am learning a lot, too.

@BernieTGN,
I was explicitly talking about equality checks :wink:

The first code of days ago is working on intraday data (also) because equality check was commented.
Take a look at below two of (several other) scenarios of the code I was talking about (that's why I said it needs to be studied a bit because of those several scenarios. I forgot to add "to carefully study" :wink: ).

isEntryDay = ExRem(dt >= fifth_day, dt < fifth_day);
// or if you want equality check instead then uncomment below line
//isEntryDay = dt == fifth_day;

In upper snippet of the code the first "isEntryDay" variable which is using Exrem either sets flag if exact date exists or it "jumps" to next existing bar if fifth_day does not exist in array. On the other hand the 2nd (commented) option of "isEntryDay" only applies equality check ("=="). So it looks for exact match.

That's why I said I have added several scenarios depending on what you want to get applied. I don't know if you want an exact lookup or if you want to get to the next or previous available bar if looked for date does not exists in array because of simply being missed (data hole) or because being weekend date or because of holiday.

Anyway.... if applying equality check and if using the 1st code of a few days ago then on intraday data there wasn't any flag set.

The updated code of today's post does now additionally work if applying equality checks on both EOD and intraday data.

2 Likes