<reponame>ericbudish/HFT-Races
'''
This module contains functions to determine the race message outcomes
'''

import pandas as pd

def get_take_outcome(S, P_Signed, msg, strict_fail):
    '''
    This function inputs a message and returns whether it is a successful take message in race at price P and side S
    This function uses RaceRlvtOutcome and checks whether the Take was successful at the race price level or better 
    (for the taker). If strict_fail is True then, only expired IOCs are considered fails.
    
    Param:
        S: side 
        P_Signed: signed price 
        msg: pd.Series containing message of interest 
        strict_fail: If strict is True then, only expired IOCs are considered fails.
    
    Return: String representing the outcome of the take message
    Please note that 'Gateway New Order (IOC)' includes both IOC and FOK,
    we use TIF to exclude FOK orders.
    '''
    outcome = msg['%sRaceRlvtOutcomeGroup' % S]
    exec_pr = msg['%sRaceRlvtBestExecPriceLvlSigned' % S]
    msg_type = msg['UnifiedMessageType']
    msg_tif = msg['TIF']
    
    if strict_fail == True:
        if outcome == 'Fail':
            if (msg_type == 'Gateway New Order (IOC)') & (msg_tif == 'IOC'):
                return 'Fail'
            else:
                return 'Unknown'
        elif outcome == 'Race Price Dependent':
            if exec_pr <= P_Signed:
                return 'Success'
            else:
                return 'Unknown'
        else:
            return 'Unknown'
    else:
        if outcome == 'Fail':
            return 'Fail'
        elif outcome == 'Race Price Dependent':
            if exec_pr <= P_Signed:
                return 'Success'
            else:
                return 'Fail'
        else:
            return 'Unknown'

def get_msg_outcome(S, P_Signed, subset_msgs, strict_fail):
    '''
    This function inputs a set of messages and returns whether those messages are 
    successful/failed Take or Cancel given a race at price P and side S.
    
    Param:
        S: side 
        P_Signed: signed price 
        subset_msgs: pd.DataFrame containing messages of interest 
        strict_fail: If strict is True, then only expired IOCs are considered fails.
        
    Return:
        outcome: pd.Series of strings representing outcomes 
    '''
    outcome = pd.Series('Unknown', index=subset_msgs.index)
    for i in subset_msgs.index:
        if subset_msgs.at[i, '%sRaceRlvtType' % S] == 'Cancel Attempt':
            outcome.at[i] = subset_msgs.at[i, '%sRaceRlvtOutcomeGroup' % S]
        else: 
            outcome.at[i] = get_take_outcome(S, P_Signed, subset_msgs.loc[i], strict_fail)
    return (outcome)

'''
This module contains functions to determine the race message outcomes
'''

import pandas as pd

def get_take_outcome(S, P_Signed, msg, strict_fail):
    '''
    This function inputs a message and returns whether it is a successful take message in race at price P and side S
    This function uses RaceRlvtOutcome and checks whether the Take was successful at the race price level or better 
    (for the taker). If strict_fail is True then, only expired IOCs are considered fails.
    
    Param:
        S: side 
        P_Signed: signed price 
        msg: pd.Series containing message of interest 
        strict_fail: If strict is True then, only expired IOCs are considered fails.
    
    Return: String representing the outcome of the take message
    Please note that 'Gateway New Order (IOC)' includes both IOC and FOK,
    we use TIF to exclude FOK orders.
    '''
    outcome = msg['%sRaceRlvtOutcomeGroup' % S]
    exec_pr = msg['%sRaceRlvtBestExecPriceLvlSigned' % S]
    msg_type = msg['UnifiedMessageType']
    msg_tif = msg['TIF']
    
    if strict_fail == True:
        if outcome == 'Fail':
            if (msg_type == 'Gateway New Order (IOC)') & (msg_tif == 'IOC'):
                return 'Fail'
            else:
                return 'Unknown'
        elif outcome == 'Race Price Dependent':
            if exec_pr <= P_Signed:
                return 'Success'
            else:
                return 'Unknown'
        else:
            return 'Unknown'
    else:
        if outcome == 'Fail':
            return 'Fail'
        elif outcome == 'Race Price Dependent':
            if exec_pr <= P_Signed:
                return 'Success'
            else:
                return 'Fail'
        else:
            return 'Unknown'

def get_msg_outcome(S, P_Signed, subset_msgs, strict_fail):
    '''
    This function inputs a set of messages and returns whether those messages are 
    successful/failed Take or Cancel given a race at price P and side S.
    
    Param:
        S: side 
        P_Signed: signed price 
        subset_msgs: pd.DataFrame containing messages of interest 
        strict_fail: If strict is True, then only expired IOCs are considered fails.
        
    Return:
        outcome: pd.Series of strings representing outcomes 
    '''
    outcome = pd.Series('Unknown', index=subset_msgs.index)
    for i in subset_msgs.index:
        if subset_msgs.at[i, '%sRaceRlvtType' % S] == 'Cancel Attempt':
            outcome.at[i] = subset_msgs.at[i, '%sRaceRlvtOutcomeGroup' % S]
        else: 
            outcome.at[i] = get_take_outcome(S, P_Signed, subset_msgs.loc[i], strict_fail)
    return (outcome)
This module contains functions to determine the race message outcomes This function inputs a message and returns whether it is a successful take message in race at price P and side S     This function uses RaceRlvtOutcome and checks whether the Take was successful at the race price level or better      (for the taker). If strict_fail is True then, only expired IOCs are considered fails.          Param:         S: side          P_Signed: signed price          msg: pd.Series containing message of interest          strict_fail: If strict is True then, only expired IOCs are considered fails.          Return: String representing the outcome of the take message     Please note that 'Gateway New Order (IOC)' includes both IOC and FOK,     we use TIF to exclude FOK orders. This function inputs a set of messages and returns whether those messages are      successful/failed Take or Cancel given a race at price P and side S.          Param:         S: side          P_Signed: signed price          subset_msgs: pd.DataFrame containing messages of interest          strict_fail: If strict is True, then only expired IOCs are considered fails.              Return:         outcome: pd.Series of strings representing outcomes