from typing import overload
import abc
import typing

import QuantConnect
import QuantConnect.Securities
import QuantConnect.Securities.CurrencyConversion
import System
import System.Collections.Generic

QuantConnect_Securities_CurrencyConversion__EventContainer_Callable = typing.TypeVar("QuantConnect_Securities_CurrencyConversion__EventContainer_Callable")
QuantConnect_Securities_CurrencyConversion__EventContainer_ReturnType = typing.TypeVar("QuantConnect_Securities_CurrencyConversion__EventContainer_ReturnType")


class ICurrencyConversion(metaclass=abc.ABCMeta):
    """Represents a type capable of calculating the conversion rate between two currencies"""

    @property
    @abc.abstractmethod
    def ConversionRateUpdated(self) -> _EventContainer[typing.Callable[[System.Object, float], None], None]:
        """Event fired when the conversion rate is updated"""
        ...

    @ConversionRateUpdated.setter
    @abc.abstractmethod
    def ConversionRateUpdated(self, value: _EventContainer[typing.Callable[[System.Object, float], None], None]):
        """Event fired when the conversion rate is updated"""
        ...

    @property
    @abc.abstractmethod
    def SourceCurrency(self) -> str:
        """The currency this conversion converts from"""
        ...

    @property
    @abc.abstractmethod
    def DestinationCurrency(self) -> str:
        """The currency this conversion converts to"""
        ...

    @property
    @abc.abstractmethod
    def ConversionRate(self) -> float:
        """The current conversion rate between SourceCurrency and DestinationCurrency"""
        ...

    @ConversionRate.setter
    @abc.abstractmethod
    def ConversionRate(self, value: float):
        """The current conversion rate between SourceCurrency and DestinationCurrency"""
        ...

    @property
    @abc.abstractmethod
    def ConversionRateSecurities(self) -> System.Collections.Generic.IEnumerable[QuantConnect.Securities.Security]:
        """The securities which the conversion rate is based on"""
        ...

    def Update(self) -> None:
        """
        Updates the internal conversion rate based on the latest data, and returns the new conversion rate
        
        :returns: The new conversion rate.
        """
        ...


class SecurityCurrencyConversion(System.Object, QuantConnect.Securities.CurrencyConversion.ICurrencyConversion):
    """Provides an implementation of ICurrencyConversion to find and use multi-leg currency conversions"""

    @property
    def ConversionRateUpdated(self) -> _EventContainer[typing.Callable[[System.Object, float], None], None]:
        """Event fired when the conversion rate is updated"""
        ...

    @ConversionRateUpdated.setter
    def ConversionRateUpdated(self, value: _EventContainer[typing.Callable[[System.Object, float], None], None]):
        """Event fired when the conversion rate is updated"""
        ...

    @property
    def SourceCurrency(self) -> str:
        """The currency this conversion converts from"""
        ...

    @property
    def DestinationCurrency(self) -> str:
        """The currency this conversion converts to"""
        ...

    @property
    def ConversionRate(self) -> float:
        """The current conversion rate"""
        ...

    @ConversionRate.setter
    def ConversionRate(self, value: float):
        """The current conversion rate"""
        ...

    @property
    def ConversionRateSecurities(self) -> System.Collections.Generic.IEnumerable[QuantConnect.Securities.Security]:
        """The securities which the conversion rate is based on"""
        ...

    @staticmethod
    def LinearSearch(sourceCurrency: str, destinationCurrency: str, existingSecurities: System.Collections.Generic.IList[QuantConnect.Securities.Security], potentialSymbols: System.Collections.Generic.IEnumerable[QuantConnect.Symbol], makeNewSecurity: typing.Callable[[QuantConnect.Symbol], QuantConnect.Securities.Security]) -> QuantConnect.Securities.CurrencyConversion.SecurityCurrencyConversion:
        """
        Finds a conversion between two currencies by looking through all available 1 and 2-leg options
        
        :param sourceCurrency: The currency to convert from
        :param destinationCurrency: The currency to convert to
        :param existingSecurities: The securities which are already added to the algorithm
        :param potentialSymbols: The symbols to consider, may overlap with existingSecurities
        :param makeNewSecurity: The function to call when a symbol becomes part of the conversion, must return the security that will provide price data about the symbol
        :returns: A new SecurityCurrencyConversion instance representing the conversion from sourceCurrency to destinationCurrency.
        """
        ...

    def Update(self) -> None:
        """
        Signals an updates to the internal conversion rate based on the latest data.
        It will set the conversion rate as potentially outdated so it gets re-calculated.
        """
        ...


class ConstantCurrencyConversion(System.Object, QuantConnect.Securities.CurrencyConversion.ICurrencyConversion):
    """Provides an implementation of ICurrencyConversion with a fixed conversion rate"""

    @property
    def ConversionRateUpdated(self) -> _EventContainer[typing.Callable[[System.Object, float], None], None]:
        """Event fired when the conversion rate is updated"""
        ...

    @ConversionRateUpdated.setter
    def ConversionRateUpdated(self, value: _EventContainer[typing.Callable[[System.Object, float], None], None]):
        """Event fired when the conversion rate is updated"""
        ...

    @property
    def SourceCurrency(self) -> str:
        """The currency this conversion converts from"""
        ...

    @property
    def DestinationCurrency(self) -> str:
        """The currency this conversion converts to"""
        ...

    @property
    def ConversionRate(self) -> float:
        """The current conversion rate"""
        ...

    @ConversionRate.setter
    def ConversionRate(self, value: float):
        """The current conversion rate"""
        ...

    @property
    def ConversionRateSecurities(self) -> System.Collections.Generic.IEnumerable[QuantConnect.Securities.Security]:
        """The securities which the conversion rate is based on"""
        ...

    def __init__(self, sourceCurrency: str, destinationCurrency: str, conversionRate: float = 1) -> None:
        """
        Initializes a new instance of the ConstantCurrencyConversion class.
        
        :param sourceCurrency: The currency this conversion converts from
        :param destinationCurrency: The currency this conversion converts to
        :param conversionRate: The conversion rate between the currencies
        """
        ...

    @staticmethod
    def Identity(sourceCurrency: str, destinationCurrency: str = None) -> QuantConnect.Securities.CurrencyConversion.ConstantCurrencyConversion:
        """
        Creates a new identity conversion, where the conversion rate is set to 1 and the source and destination currencies might the same
        
        :param sourceCurrency: The currency this conversion converts from
        :param destinationCurrency: The currency this conversion converts to. If null, the destination and source currencies are the same
        :returns: The identity currency conversion.
        """
        ...

    @staticmethod
    def Null(sourceCurrency: str, destinationCurrency: str) -> QuantConnect.Securities.CurrencyConversion.ConstantCurrencyConversion:
        """Returns an instance of ConstantCurrencyConversion that represents a null conversion"""
        ...

    def Update(self) -> None:
        """Marks the conversion rate as potentially outdated, needing an update based on the latest data"""
        ...


class _EventContainer(typing.Generic[QuantConnect_Securities_CurrencyConversion__EventContainer_Callable, QuantConnect_Securities_CurrencyConversion__EventContainer_ReturnType]):
    """This class is used to provide accurate autocomplete on events and cannot be imported."""

    def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> QuantConnect_Securities_CurrencyConversion__EventContainer_ReturnType:
        """Fires the event."""
        ...

    def __iadd__(self, item: QuantConnect_Securities_CurrencyConversion__EventContainer_Callable) -> None:
        """Registers an event handler."""
        ...

    def __isub__(self, item: QuantConnect_Securities_CurrencyConversion__EventContainer_Callable) -> None:
        """Unregisters an event handler."""
        ...


