Function that returns index of Forex candle according opening hours (weekly session) The output of the function is as desired. When Forex opens at Sunday, first candle is annotated with 1 and the number increments with every new candle, till weekend, when the imaginary counter is reset.

I am aware of those risks (it is solved elsewhere):


passed datetime must be python datetime 
time must be in GMT


My concerns are about readability and optimality of the code. Any advice?

def weektag_from_time(timestamp, freq):
    """
    This function returns index of the current time in Forex session,
    according to chosen granularity.
    Forex session - Sunday 2200 to Friday 2200.
    If the session is off, it should return 0.

    Args:
        * timestamp : python datetime in GMT
        * freq : desired granularity (minute, hour, ...)

    Returns:
        * weektag : integer index in Forex session
    """
    # init
    assert freq in ["H1", "M1"], "Required granularity is not known."
    d = timestamp.weekday()
    h = timestamp.hour
    m = timestamp.minute
    # get tag
    if (d == 5) or (d == 4 and h &gt; 21) or (d == 6 and h &lt; 22):
        # market is closed
        weektag = 0
    else:
        # estimate week day offset in hours and add it to current day hours
        offset = (24*d)+2 if d &lt; 6 else -22
        h += offset
        # set result according granularity
        if freq == "H1":
            weektag = h
        elif freq == "M1":
            weektag = (h*60) + m
    return weektag
The code overall is readable and well documented. Of course, there is always something to improve, here are some things:


the frequencies are currently hardcoded in the function and the "assert" is not actually a strong check and would not prevent an invalid freq value to be used if Python compilation is optimized. I'd define frequencies in an Enum class:

from enum import Enum


class Frequency(Enum):
     HOURLY = "H1"
     MINUTELY = "M1"


Then, as a bonus, if you would use variable type annotations, your IDE would warn you if you would pass an invalid frequency to the weektag_from_time() function.
use day, hour and minute in place of more questionable d, h and m - remember, we are writing programs for people to read, not computers
I would improve on the "is market closed" check defining individual conditions in separate variables (the "Extract Variable" refactoring method), something like

is_saturday = day == 5
is_late_friday = day == 4 and hour &gt; 21
is_early_sunday = day == 6 and hour &lt; 22

market_closed = is_friday or is_late_thursday or is_early_saturday

or, may be even easier and more understandable would be to define an open market time range and reverse the logic. And, it might be a good idea to extract this check into a separate reusable function (I'm sure you have this kind of check in other parts of your project).
now, we may use an early "return" if market is closed and omit the "else" part decreasing the nestedness:

if market_closed:
    return 0

offset = (24 * day) + 2 if day &lt; 6 else -22
hour += offset

# set result according granularity
if freq == Frequency.HOURLY:
    return hour
elif freq == Frequency.MINUTELY:
    return (hour * 60) + minute

according to PEP8, you should have spaces around operators
the offset calculation logic probably needs more explanation - consider adding an extra comment explaining the idea behind calculating it