Esempio n. 1
0
class MockBroker():
    def __init__(self):
        self.wallet = 1000;
        self.stat = Stat()

        self.trades = []

    def get_tick_data(self, instrument):
        while True:
            tick = (datetime.now(), 2, 1)
            self.stat.add_tick(tick)
            yield tick

    def open(self, instrument, volume):
        # register trade

        return Trade(instrument, volume)

    def close(self, trade):
        pass

    def convert_currency(self, instrument, base_volume, rate=None):
        if rate:
            return base_volume * rate
        else:
            tick = self.get_tick_data(instrument)

            if base_volume > 0: # buy
                return tick[1] * base_volume
            else: # sell
                return tick[2] * abs(base_volume)

    def get_account_info(self):
        self.margin_rate = 0.05
        self.account_currency = 'EUR'

    def get_account_state(self):
        self.wallet = 1000
        self.trades = self.get_active_trades()

    def get_active_trades(self):
        return []
Esempio n. 2
0
class TestBrokerLocal():
    def __init__(self, account_balance, margin_rate, tick_source, account_currency="EUR"):
        self.account_id = None
        self.account_name = 'Local test'
        self.account_currency = account_currency
        self.margin_rate = margin_rate

        self.balance = account_balance
        self.margin_available = account_balance
        self.margin_used = 0.0

        self.open_orders = 0
        self.open_orders_list = []
        self.open_trades = 0
        self.open_trades_list = []

        self.realized_pl = 0
        self.unrealized_pl = 0

        self.tick_source = Driver.init_module_config(tick_source)

        self.stat = Stat(account_balance)
        self.last_tick = {}

        self.logger = logging.getLogger(__name__)

    def __str__(self):
        ret = "Local test broker"
        ret += "account id: " + str(self.account_id) + "\n"
        ret += "account name: " + str(self.account_name) + "\n"
        ret += "account currency: " + str(self.account_currency) + "\n"
        ret += "balance: " + str(self.balance) + "\n"
        ret += "margin available: " + str(self.margin_available) + "\n"
        ret += "margin used: " + str(self.margin_used) + "\n"
        ret += "margin rate:  " + str(self.margin_rate) + "\n"
        ret += "realized pl: " + str(self.realized_pl) + "\n"
        ret += "unrealized pl:  " + str(self.unrealized_pl) + "\n"
        return ret

    def get_tick_data(self, instrument):
        for tick in self.tick_source.get_tick_data(instrument):
            self.stat.add_tick(tick)
            self.last_tick[instrument] = tick

            # close finished sl/tp trades
            self.open_trades_list = self.close_finished_trades(self.open_trades_list)

            yield tick

    def open(self, instrument, volume, order_type='market', expiry=None, **args):  # price=None, lower_bound=None, upper_bound=None, sl=None, tp=None, ts=None):
        if order_type == 'market':
            if volume > 0:
                open_price = self.last_tick[instrument].buy
            elif volume < 0:
                open_price = self.last_tick[instrument].sell

            trade = Trade(instrument=instrument,
                          volume=volume,
                          open_price=open_price,
                          open_datetime=self.last_tick[instrument].datetime)
            trade_margin = (abs(volume) * open_price) * self.margin_rate
            if self.margin_available - trade_margin < 0:
                print("Not enough money to open the trade")
                return None
            else:
                self.margin_available -= trade_margin
                self.margin_used += trade_margin
                self.open_trades += 1
                self.open_trades_list.append(trade)
                return trade
        else:
            self.logger.warning("oreder_type is not 'market' - not implemented yet")

    def close(self, trade):
        if trade.volume > 0:
            close_price = self.last_tick[trade.instrument].sell
        elif trade.volume < 0:
            close_price = self.last_tick[trade.instrument].buy

        trade.close(close_price, self.last_tick[trade.instrument].datetime)
        trade_margin = (abs(trade.volume) * close_price) * self.margin_rate

        self.margin_available += trade_margin
        self.margin_used -= trade_margin

        # get profit
        pl = (trade.close_rate - trade.open_rate) * abs(trade.volume)
        self.realized_pl += pl
        self.balance += pl
        trade.set_profit(pl)

        self.stat.add_trade(trade)
        return trade

    def convert_currency(self, instrument, base_volume, rate=None):
        if rate:
            return base_volume * rate
        else:
            tick = self.get_tick_data(instrument)

            if base_volume > 0: # buy
                return tick.buy * base_volume
            else: # sell
                return tick.sell * abs(base_volume)

    def close_finished_trades(self, trades):
        """
        Checks for sl/tp out. This method simulates what the real broker does and must
        be called from model after processing each new tick..
        TODO: trailing stoploss
        Arguments:
            trades list of all trades the model has opened
        Returns:
            list of trades left open
        """
        left_trades = []
        for trade in trades:
            if trade.volume > 0:
                if trade.sl:
                    if self.last_tick[trade.instrument] <= trade.sl:
                        self.close(trade)
                    else:
                        left_trades.append(trade)
                if self.tp:
                    if self.last_tick[trade.instrument] >= trade.tp:
                        self.close(trade)
                    else:
                        left_trades.append(trade)
            else:
                if trade.sl:
                    if self.last_tick[trade.instrument] >= trade.sl:
                        self.close(trade)
                    else:
                        left_trades.append(trade)
                if self.tp:
                    if self.last_tick[trade.instrument] <= trade.tp:
                        self.close(trade)
                    else:
                        left_trades.append(trade)
        return left_trades

    def get_account(self):
        """Does nothing in local implementation
        """
        None

    def get_account_information(self):
        """Does nothing in local implementation
        """
        None

    def get_open_trades(self):
        return []
Esempio n. 3
0
class TestBrokerLocal():
    def __init__(self, account_balance, margin_rate, tick_source, account_currency="EUR"):
        self.param_account_balance = account_balance
        self.param_margin_rate = margin_rate
        self.param_tick_source = tick_source
        self.param_account_currency = account_currency

        self.reset_broker()

        self.logger = logging.getLogger(__name__)

    def reset_broker(self):
        self.account_id = None
        self.account_name = 'Local test'
        self.account_currency = self.param_account_currency
        self.margin_rate = self.param_margin_rate

        self.balance = self.param_account_balance
        self.margin_available = self.param_account_balance
        self.margin_used = 0.0

        self.open_orders = 0
        self.open_orders_list = []
        self.open_trades = 0
        self.open_trades_list = []
        self.trade_id = 0

        self.realized_pl = 0
        self.unrealized_pl = 0

        self.tick_source = Driver.init_module_config(self.param_tick_source)

        self.stat = Stat(self.param_account_balance)
        self.last_tick = {}

    def __str__(self):
        ret = "Local test broker"
        ret += "account id: " + str(self.account_id) + "\n"
        ret += "account name: " + str(self.account_name) + "\n"
        ret += "account currency: " + str(self.account_currency) + "\n"
        ret += "balance: " + str(self.balance) + "\n"
        ret += "margin available: " + str(self.margin_available) + "\n"
        ret += "margin used: " + str(self.margin_used) + "\n"
        ret += "margin rate:  " + str(self.margin_rate) + "\n"
        ret += "realized pl: " + str(self.realized_pl) + "\n"
        ret += "unrealized pl:  " + str(self.unrealized_pl) + "\n"
        return ret

    def get_tick_data(self, instrument):
        for tick in self.tick_source.get_tick_data(instrument):
            self.stat.add_tick(tick)
            self.last_tick[instrument] = tick

            # close finished sl/tp trades
            self.open_trades_list = self.close_finished_trades(self.open_trades_list)

            yield tick

    def open(self, instrument, volume, order_type='market', expiry=None, **args):  # price=None, lower_bound=None, upper_bound=None, sl=None, tp=None, ts=None):
        if order_type == 'market':
            if volume > 0:
                open_price = self.last_tick[instrument].buy
            elif volume < 0:
                open_price = self.last_tick[instrument].sell

            trade = Trade(instrument=instrument,
                          volume=volume,
                          open_price=open_price,
                          open_datetime=self.last_tick[instrument].datetime, 
                          id=self.trade_id, **args)

            # calculate margin and convert it to the account currency if needed
            trade_margin = abs(trade.volume) * self.margin_rate
            trade_margin_converted = self.convert_to_account_currency(trade_margin, trade.instrument[0])

            if self.margin_available - trade_margin_converted < 0:
                self.logger.warning("not enough money to open the trade")
                return None
            else:
                self.margin_available -= trade_margin_converted
                self.margin_used += trade_margin_converted
                self.open_trades += 1
                self.open_trades_list.append(trade)
                self.trade_id += 1
                return trade
        else:
            self.logger.warning("oreder_type is not 'market' - not implemented yet")
            return None

    def close(self, trade):
        if trade.volume > 0:
            close_price = self.last_tick[trade.instrument].sell
        elif trade.volume < 0:
            close_price = self.last_tick[trade.instrument].buy

        if trade in self.open_trades_list:
            self.open_trades_list.remove(trade)
        else:
            print(trade.id, "not in trade list!!")
            return None

        trade.close(close_price, self.last_tick[trade.instrument].datetime)

        # calculate margin and convert it to the account currency if needed
        trade_margin = abs(trade.volume) * self.margin_rate
        trade_margin_converted = self.convert_to_account_currency(trade_margin, trade.instrument[0])
        self.margin_available += trade_margin_converted
        self.margin_used -= trade_margin_converted

        # get profit in quote currency and convert it to the base currency
        quote_pl = (trade.close_rate - trade.open_rate) * trade.volume
        pl = round(self.convert_to_account_currency(quote_pl, trade.instrument[1]), 4)
        self.realized_pl += pl
        self.balance += pl
        trade.set_profit(pl)

        self.stat.add_trade(trade)
        return trade

    def convert_from_account_currency(self, volume, target_currency):
        if target_currency == self.account_currency:
            return volume
        else:
            if self.last_tick[(self.account_currency, target_currency)]:
                return volume * self.last_tick[(self.account_currency, target_currency)].buy
            else:
                tick = self.get_tick_data((self.account_currency, target_currency)).__next__()
                return volume * tick.buy

    def convert_to_account_currency(self, volume, source_currency):
        if source_currency == self.account_currency:
            return volume
        else:
            if self.last_tick[(self.account_currency, source_currency)]:
                return volume * (1.0 /self.last_tick[(self.account_currency, source_currency)].buy)
            else:
                tick = self.get_tick_data((self.account_currency, source_currency)).__next__()
                return volume * (1.0 /tick.buy)

    def close_finished_trades(self, trades):
        """
        Checks for sl/tp out. This method simulates what the real broker does and must
        be called from model after processing each new tick..
        TODO: trailing stoploss
        Arguments:
            trades list of all trades the model has opened
        Returns:
            list of trades left open
        """
        left_trades = []
        for trade in trades:
            if trade.sl or trade.tp:
                close = False
                if trade.volume > 0:
                    if trade.sl:
                        if self.last_tick[trade.instrument].sell <= trade.sl:
                            self.logger.info("trade closed with stop loss")
                            close = True
                    if trade.tp:
                        if self.last_tick[trade.instrument].sell >= trade.tp:
                            self.logger.info("trade closed with take profit")
                            close = True
                else:
                    if trade.sl:
                        if self.last_tick[trade.instrument].buy >= trade.sl:
                            self.logger.info("trade closed with stop loss")
                            close = True
                    if trade.tp:
                        if self.last_tick[trade.instrument].buy <= trade.tp:
                            self.logger.info("trade closed with take profit")
                            close = True
                if close:
                    result = self.close(trade)
                    self.logger.info("profit: result.profit")
                else:
                    left_trades.append(trade)
            else:
                left_trades.append(trade)
        return left_trades

    def get_account(self):
        """Does nothing in local implementation
        """
        None

    def get_account_information(self):
        """Does nothing in local implementation
        """
        None

    def get_open_trades(self):
        return copy.deepcopy(self.open_trades_list)