Retrives symbol's ID from the Database or create it if it doesn't exist

    :Parameters:
        symbol : str
            Instrument symbol
        dbconn : object
            Database connection to be used
        dbcurr : object
            Database cursor to be used

    :Optional:
        ibConn : object
            ezIBpy object (used for determining futures/options expiration)

    :Returns:
        symbol_id : int
            Symbol ID

def get_symbol_id(symbol, dbconn, dbcurr, ibConn=None):
    """
    Retrives symbol's ID from the Database or create it if it doesn't exist

    :Parameters:
        symbol : str
            Instrument symbol
        dbconn : object
            Database connection to be used
        dbcurr : object
            Database cursor to be used

    :Optional:
        ibConn : object
            ezIBpy object (used for determining futures/options expiration)

    :Returns:
        symbol_id : int
            Symbol ID
    """
    def _get_contract_expiry(symbol, ibConn=None):
        # parse w/p ibConn
        if ibConn is None or isinstance(symbol, str):
            return tools.contract_expiry_from_symbol(symbol)

        # parse with ibConn
        contract_details = ibConn.contractDetails(symbol)["m_summary"]
        if contract_details["m_expiry"] == "":
            ibConn.createContract(symbol)
            return _get_contract_expiry(symbol, ibConn)

        if contract_details["m_expiry"]:
            return datetime.strptime(str(contract_details["m_expiry"]), '%Y%m%d'
                                     ).strftime("%Y-%m-%d")

        return contract_details["m_expiry"]

    # start
    asset_class = tools.gen_asset_class(symbol)
    symbol_group = tools.gen_symbol_group(symbol)
    clean_symbol = symbol.replace("_" + asset_class, "")
    expiry = None

    if asset_class in ("FUT", "OPT", "FOP"):
        expiry = _get_contract_expiry(symbol, ibConn)

        # look for symbol w/ expiry
        sql = """SELECT id FROM `symbols` WHERE
            `symbol`=%s AND `symbol_group`=%s AND `asset_class`=%s  AND `expiry`=%s LIMIT 1"""
        dbcurr.execute(sql, (clean_symbol, symbol_group, asset_class, expiry))

    else:
        # look for symbol w/o expiry
        sql = """SELECT id FROM `symbols` WHERE
            `symbol`=%s AND `symbol_group`=%s AND `asset_class`=%s LIMIT 1"""
        dbcurr.execute(sql, (clean_symbol, symbol_group, asset_class))

    row = dbcurr.fetchone()

    # symbol already in db
    if row is not None:
        return row[0]

    # symbol/expiry not in db... insert new/update expiry
    else:
        # need to update the expiry?
        if expiry is not None:
            sql = """SELECT id FROM `symbols` WHERE
                `symbol`=%s AND `symbol_group`=%s AND `asset_class`=%s LIMIT 1"""
            dbcurr.execute(sql, (clean_symbol, symbol_group, asset_class))

            row = dbcurr.fetchone()
            if row is not None:
                sql = "UPDATE `symbols` SET `expiry`='" + \
                    str(expiry) + "' WHERE id=" + str(row[0])
                dbcurr.execute(sql)
                try:
                    dbconn.commit()
                except Exception as e:
                    return False
                return int(row[0])

        # insert new symbol
        sql = """INSERT IGNORE INTO `symbols`
            (`symbol`, `symbol_group`, `asset_class`, `expiry`) VALUES (%s, %s, %s, %s)
            ON DUPLICATE KEY UPDATE `symbol`=`symbol`, `expiry`=%s
        """

        dbcurr.execute(sql, (clean_symbol, symbol_group,
                             asset_class, expiry, expiry))
        try:
            dbconn.commit()
        except Exception as e:
            return False

        return dbcurr.lastrowid