ib-api-reloaded / ib_async

Python sync/async framework for Interactive Brokers API (replaces ib_insync)
BSD 2-Clause "Simplified" License
465 stars 73 forks source link

Update ContractDetails #3

Open ClimberMel opened 8 months ago

ClimberMel commented 8 months ago

These fund items have been added under def ContractDetails

      # FUND values
        self.fundName = ""
        self.fundFamily = ""
        self.fundType = ""
        self.fundFrontLoad = ""
        self.fundBackLoad = ""
        self.fundBackLoadTimeInterval = ""
        self.fundManagementFee = ""
        self.fundClosed = False
        self.fundClosedForNewInvestors = False
        self.fundClosedForNewMoney = False
        self.fundNotifyAmount = ""
        self.fundMinimumInitialPurchase = ""
        self.fundSubsequentMinimumPurchase = ""
        self.fundBlueSkyStates = ""
        self.fundBlueSkyTerritories = ""
        self.fundDistributionPolicyIndicator = FundDistributionPolicyIndicator.NoneItem
        self.fundAssetType = FundAssetType.NoneItem

Also this code has been added at the end:

class FundAssetType(Enum):
    NoneItem = ("None", "None")
    Others = ("000", "Others"), 
    MoneyMarket = ("001", "Money Market")
    FixedIncome = ("002", "Fixed Income")
    MultiAsset = ("003", "Multi-asset")
    Equity = ("004", "Equity")
    Sector = ("005", "Sector")
    Guaranteed = ("006", "Guaranteed")
    Alternative = ("007", "Alternative")

class FundDistributionPolicyIndicator(Enum):
    NoneItem = ("None", "None")
    AccumulationFund = ("N", "Accumulation Fund")
    IncomeFund = ("Y", "Income Fund")

def listOfValues(cls):
    return list(map(lambda c: c, cls))

def getEnumTypeFromString(cls, stringIn):
    for item in cls:
        if item.value[0] == stringIn:
            return item
    return listOfValues(cls)[0]

def getEnumTypeName(cls, valueIn):
    for item in cls:
        if item == valueIn:
            return item.value[1]
    return listOfValues(cls)[0].value[1]
mattsta commented 8 months ago

Indeed! It's on the todo list. We'll need to make some new classes and types and add these new details to the protocol parser for those fields.

Most of the work will be a refactor of the twsapi/ibapi python implementation's protocol decoder in ibapi/decoder.py around here:

        if (
            self.serverVersion >= MIN_SERVER_VER_FUND_DATA_FIELDS
            and contract.contract.secType == "FUND"
        ):
ClimberMel commented 8 months ago

Did you want to add me to the repo and I can assign this to myself?

mattsta commented 8 months ago

Thanks! Yeah, feel free to give it a try. These are a different input format than anything else, so it may take some decisions to figure out what goes where and how.

I'll select you on the assigned field and just drop a PR if it looks good enough to review. I'd be curious to test it too but I don't know what symbols are this FUND type yet. Maybe we can even try to add some automated test cases for it (against a readonly gateway?).

Looking through it a bit, those Enum cases are just weird/bad. The reason their format is like ("001", "Money Market") is because the ibapi decoder is reading 001 from the IBKR protocol then replacing it with Money Market on the returned object for the user to see.

BUT — these should just be dicts mapping the key to the enum value then? They have that awful thing called getEnumTypeFromString() which just linearly searches each enum if x[0] == value? why would they do it that way? it's 10x more difficult than just using a dict for those mappings. more like lookupFundAssetType: dict[str, FundAssetType] = {"None": FundAssetType.NoneItem, "001": FundAssetType.MoneyMarket, ...} etc?

gnzsnz commented 7 months ago

@ClimberMel have you been able to progress on this one?

ClimberMel commented 7 months ago

No, I got sidetracked. I was having trouble finding example to test it with. I'm not familiar with bonds, and that is all these changes pertain to.

mattsta commented 7 months ago

Yeah, testing this would be a bit weird. Probably just making it match the existing twsapi interface should be good enough then people can complain if it doesn't work. I think these are only informational APIs anyway and don't impact trading at all?

I can look through it again to see what matches for adapting if your attempts have run out of steam.

ClimberMel commented 7 months ago

You know that's not a bad idea, I have the code changes so I'll upload them and wait to see if anyone uses them.