No, it’s not.
You can put them anywhere in the file if you first declare their existence before they are used for the first time. If the compiler doesn’t know about the existence of the function before it encounters it’s first use, it will spit the dummy.
The Arduino IDE has a preprocessor system (Arduino builder) which does things in a non-C/C+±standard manner - such as generating function prototypes itself, and mashing all the open tabs in a sketch together, making it a single file.
It’s just easier to shove the setup and loop at the end of the file, then you don’t need to declare prototypes at all since they’ll have all defined by the time they are called in setup or loop.