def get_total_profit_for_pair(symbol): buy_prices = Trade.select(Trade.price).where(Trade.symbol == symbol, Trade.side == 'BUY').dicts() sell_prices = Trade.select(Trade.price).where( Trade.symbol == symbol, Trade.side == 'SELL').dicts() if len(buy_prices) <= 0 or len(sell_prices) <= 0: return buy_prices = list(price['price'] for price in buy_prices) sell_prices = list(price['price'] for price in sell_prices) buy_prices_average = sum(buy_prices) / len(buy_prices) sell_prices_average = sum(sell_prices) / len(sell_prices) price_difference = sell_prices_average / buy_prices_average buy_qty = Trade.select(Trade.quantity).where(Trade.symbol == symbol, Trade.side == 'BUY').dicts() sell_qty = Trade.select(Trade.quantity).where( Trade.symbol == symbol, Trade.side == 'SELL').dicts() if len(buy_qty) <= 0 or len(sell_qty) <= 0: return buy_qty = list(qty['quantity'] for qty in buy_qty) sell_qty = list(qty['quantity'] for qty in sell_qty) buy_qty_sum = sum(buy_qty) sell_qty_sum = sum(sell_qty) executed_qty = min(buy_qty_sum, sell_qty_sum) profit = (price_difference - 1) * executed_qty return profit
def save_trade(signal_type, signal_id, order, trade_type): order_date = datetime.utcfromtimestamp(order['transactTime'] / 1000).strftime('%Y-%m-%d') order_time = datetime.utcfromtimestamp(order['transactTime'] / 1000).strftime('%H:%M:%S') for fill in order['fills']: trade = Trade( order_date=order_date, order_time=order_time, signal_type=signal_type, signal_id=signal_id, symbol=order['symbol'], side=order['side'], price=float(fill['price']), quantity=float(fill['qty']), quantity_asset=split_symbol(order['symbol'])['base'], fee=float(fill['commission']), fee_asset=fill['commissionAsset'], order_id=order['orderId'], status=order['status'], type=trade_type, rsi_5m=get_rsi_value(order['symbol'], '5M'), rsi_1h=get_rsi_value(order['symbol'], '1H'), price_change_percent_difference=get_price_change_percent_difference( order['symbol']), order_timestamp=order['transactTime'], date_create=int(time.time())) trade.save()
def check_pump(): print("Looking for Buy Opportunities...") threading.Thread(target=check_sell).start() while True: try: open_orders = db.query(Trade).all() for symbol in symbols: r2 = requests.get( "https://api.binance.com/api/v1/ticker/24hr?symbol=" + symbol).json() prices[symbol] = '{0:.8f}'.format( round(float(r2['lastPrice']), 8)) pct_change = float(r2['priceChangePercent']) if round(float(prices[symbol]), 8) < float(prices[symbol])*(1 + expected_change_buy/100) \ and pct_change > expected_change_buy: # print(pct_change, expected_change_buy) current_symbol = symbol if current_symbol not in open_orders: min_price, min_Qty = calculate_min(current_symbol) temp_price = float( prices[symbol]) * final_buy_price_change final_buy_price = temp_price - (temp_price % float(min_price)) temp_quantity = buy_quantity_btc / float( final_buy_price) quantity = round((temp_quantity - ((temp_quantity % float(min_Qty)))), 8) try: trade = Trade.find(symbol) if trade is None: order = client.order_limit_buy( # Place order for buy symbol=current_symbol, recvWindow=1000, quantity='{0:.3f}'.format(float(quantity)), price='{0:.8f}'.format( float(final_buy_price))) print("Buy: " + symbol + ' at: ' + str('{0:.8f}'.format( float(prices[symbol]) * final_buy_price_change)) + " from " + str(prices[symbol]) + " Due to change % " + str(pct_change)) trade = Trade.get_or_create(symbol) trade.price = str('{0:.8f}'.format( float(prices[symbol]))) trade.orderId = order['orderId'] trade.quantity = str('{0:.3f}'.format( float(quantity))) db.commit() check_buy_status(symbol) else: continue except Exception as e: # print(e) pass time.sleep(5) except Exception as e: print(e)
def testPriceForBuyTrade(self): prediction_key = Prediction(contract_one=0.00, contract_two=0.00, liquidity=100, statement="Test", end_time=datetime.datetime.now()).put() user_key = Profile().put() trade = Trade(prediction_id=prediction_key, user_id=user_key, direction='BUY', contract='CONTRACT_ONE', quantity=10.00) priceBuy = get_price_for_trade(prediction_key.get(), trade) self.assertEqual(5.124947951362557, priceBuy) prediction_key = Prediction(contract_one=10.00, contract_two=0.00, liquidity=100, statement="Test", end_time=datetime.datetime.now()).put() trade = Trade(prediction_id=prediction_key, user_id=user_key, direction='SELL', contract='CONTRACT_ONE', quantity=10.00) priceSale = get_price_for_trade(prediction_key.get(), trade) self.assertEqual(-5.124947951362557, priceSale)
def test_invalid_trade(self): buy = createBuy() # Orders shouldn't should only fill to opposing side assert not Trade.create(buy, buy) # Order shouldn't match if the prices don't intersect assert not Trade.create(buy, createSell(price=101))
def create(self): """Create a trade from the instance created by the constructor""" Trade.create( user_one=self.user_one, user_two=self.user_two, book_one=self.book_one, book_two=self.book_two, status=self.status )
def localbitcoins_store_in_db_all_new_trades(): logger.debug('getting all existing tids from database') all_trades = session.query(Trade.source_id).all() existing_tids = [int(x[0]) for x in all_trades] logger.debug('got %d tids', len(existing_tids)) oldest_max_tid = max(existing_tids) trades = localbitcoins_trades(max_tid=None) if not set([t['tid'] for t in trades]).issubset(existing_tids): added_tids = [] not_added_tids = [] for t in trades: if t['tid'] > oldest_max_tid: session.add(Trade(source_id=t['tid'], date=datetime.datetime.utcfromtimestamp(int(t['date'])), amount=Decimal(t['amount']), price=Decimal(t['price']), source='localbitcoins')) added_tids.append(t['tid']) else: not_added_tids.append(t['tid']) if added_tids: logger.debug('added tids %s to session', str(added_tids)) if not_added_tids: logger.debug('not added tids %s to session', str(not_added_tids)) session.commit() logger.debug('committed new records') else: logger.debug('trades table seems up to date') return max_tid = trades[-1]['tid']-1 while len(trades) == 500 and not set([t['tid'] for t in trades]).issubset(existing_tids): logger.debug('max_tid for next request is %s', max_tid) trades = localbitcoins_trades(max_tid) added_tids = [] not_added_tids = [] for t in trades: if t['tid'] > oldest_max_tid: session.add(Trade(source_id=t['tid'], date=datetime.datetime.utcfromtimestamp(int(t['date'])), amount=Decimal(t['amount']), price=Decimal(t['price']), source='localbitcoins')) added_tids.append(t['tid']) else: not_added_tids.append(t['tid']) if added_tids: logger.debug('added tids %s to session', str(added_tids)) if not_added_tids: logger.debug('not added tids %s to session', str(not_added_tids)) session.commit() logger.debug('committed new records') max_tid = trades[-1]['tid'] session.commit()
def create_trade(user_one=None, user_two=None, book_one=None, book_two=None, status="processing"): """Static method to create trade.""" Trade.create( user_one=user_one, user_two=user_two, book_one=book_one, book_two=book_two, status=status )
def fire_etf_orders(trades_df, side, now, strategy, apis, server, algo="echo"): for trades in trades_df.iterrows(): try: live_trade = Trade(trades[1].symbol, trades[1].posdifference, side, now, strategy) live_trade.submitOrder(apis, server, algo=algo) except: logging.warning("Trade failed for", trades[1].symbol)
def get_all_trades_by_user(username): """This method return a list of all trades that the user is involved with.""" trades = [] as_primary = Trade.select().where(Trade.user_one == username) as_secondary = Trade.select().where(Trade.user_two == username) for t in as_primary: trades.append(t) for t in as_secondary: trades.append(t) return trades
def __init__(self, tickers, test=False): self.test = test self.tickers = tickers self.ticker = self.tickers[0] self.start_ticker = self.tickers[-1] (self.diff, self.diff_pct) = calc_diff( self.start_ticker.price, self.ticker.price) self.buys = Trade.select().where(Trade.test == self.test, Trade.currency == self.ticker.currency, Trade.type == 'buy').count() self.sells = Trade.select().where(Trade.test == self.test, Trade.currency == self.ticker.currency, Trade.type == 'sell').count()
def test_items_must_belong_to_their_respective_owners(self): user_from = User('*****@*****.**', 'abe', '1234') user_to = User('*****@*****.**', 'lincoln', '4321') item_from = Item(user=user_from) item_to = Item(user=user_to) self.db.add_all([user_from, user_to, item_from, item_to]) self.db.commit() # from to swap with self.assertRaises(AssertionError): trade = Trade(user_from_id=user_from.id, user_to_id=user_to.id, item_from=item_to, item_to=item_from) # to from swap with self.assertRaises(AssertionError): trade = Trade(user_from_id=user_to.id, user_to_id=user_from.id, item_to=item_to, item_from=item_from)
def CreateTrade(): """Creates a trade for the user.""" user_id = users.get_current_user().user_id() user_key = ndb.Key('Profile', user_id) current_user = user_key.get() prediction_key = ndb.Key(urlsafe=request.form['prediction_id']) prediction = prediction_key.get() if request.form['is_likelihood'] == 'true': user_id = users.get_current_user().user_id() user_key = ndb.Key('Profile', user_id) current_user = user_key.get() trade = calculate_trade_from_likelihood( float(request.form['likelihood']), prediction, current_user) print trade else: trade = Trade(prediction_id=prediction_key, user_id=user_key, direction=request.form['direction'], contract=request.form['contract'], quantity=float(request.form['quantity'])) err = CreateTradeAction(prediction, current_user, trade) #TODO replace with error if err != 'error': flash('You successfully predicted!') return redirect('/predictions/' + trade.prediction_id.urlsafe())
def post_trades(self, trades, raw_json=None): with create_session() as session: account = session.query(AccountModel).filter_by( api_key=self.api_key).first() for trade_params in trades: trade_id = trade_params['id'] trade_in_db = session.query(Trade).filter_by( tradeId=trade_id).first() if not trade_in_db: trade = Trade( tradeId=trade_params['id'], orderId=trade_params['orderId'], symbol=trade_params['symbol'], price=trade_params['price'], qty=trade_params['qty'], commission=trade_params['commission'], commissionAsset=trade_params['commissionAsset'], time=datetime.fromtimestamp( float(trade_params['time']) / 1000), isBuyer=trade_params['isBuyer'], isMaker=trade_params['isMaker'], isBestMatch=trade_params['isBestMatch'], account=account, raw_json=trade_params if not raw_json else raw_json) session.add(trade) session.commit() return True
def generate_trade_history(session, page_size=None, offset=None, sort_column=None, sort_order="ASC"): trades = Trade.get_last_trades(session, page_size, offset, sort_column, sort_order) trade_list = [] for trade in trades: trade_list.append( [ trade.id, trade.symbol, trade.side, trade.price, trade.size, trade.buyer_id, trade.seller_id, trade.buyer_username, trade.seller_username, trade.created, trade.order_id, trade.counter_order_id, ] ) return trade_list # trades = Trade.get_last_trades( session, since ).all() # return trades pass
def index(): with open('sexycaracas.json') as f: providers = json.loads(f.read()) with open('vesusd.json') as f: vesusd = json.loads(f.read()) with open('chaturbate.json') as f: s = f.read() streams = json.loads(s) if request.args.get('cb', False) != False: cb = True else: cb = False sc = session.query(SexProviderSnapshot).filter(SexProviderSnapshot.available==True).order_by(SexProviderSnapshot.price.asc()).all() prices_sc = [float(p.price) for p in sc] stats_sc = {'mean': int(np.mean(prices_sc)), 'median': int(np.median(prices_sc)), 'min': min(prices_sc), 'max': max(prices_sc)} last_trades = Trade.last_trades(100, result=(Trade.date, Trade.amount, Trade.price)) last_trades.reverse() last_trades = tuple((trade[0].replace(tzinfo=datetime.timezone.utc).astimezone(tz=pytz.timezone('America/Caracas')).replace(tzinfo=None), locale.format('%.8f', trade[1], grouping=True), locale.format('%.2f', trade[2], grouping=True), locale.format('%.2f', trade[1]*trade[2], grouping=True)) for trade in last_trades) if streams['good']: stream = streams['good'][0] else: stream = None music_tags = ['<iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=158016030/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/transparent=true/" name="{}" seamless><a href="http://galaxie500.bandcamp.com/album/on-fire">On Fire by Galaxie 500</a></iframe>'.format(int(datetime.datetime.utcnow().timestamp())), '<iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=1696464046/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/transparent=true/" name="{}" seamless><a href="http://pwelverumandsun.bandcamp.com/album/dont-wake-me-up">Don't Wake Me Up by the Microphones</a></iframe>'.format(int(datetime.datetime.utcnow().timestamp())),] return render_template('index.html', stats_sc=stats_sc, vesusd=vesusd, last_trades=last_trades, sc_urls=[sc[0].source_url, random.choice([x for x in sc if int(x.price) == stats_sc['median']]).source_url, sc[-1].source_url], stream=stream, music_tag=random.choice(music_tags), cb=cb)
def get_base_wallet_value(test=False): trades = Trade.select().where(Trade.test == test).order_by( Trade.date.asc()) buy_count = 0 sell_count = 0 total_bought = 0 total_sold = 0 value_invested = 0 # total amount needed to make these trades (capital needed) highest_amount_entered = 0 for trade in trades: order_amount = trade.quantity * trade.price if trade.type == 'buy': buy_count += 1 total_bought += order_amount value_invested += order_amount if trade.type == 'sell': sell_count += 1 total_sold += order_amount value_invested -= order_amount if value_invested > highest_amount_entered: highest_amount_entered = value_invested print('BUYS: {} \t => {}{}'.format(buy_count, total_bought, CURRENCY)) print('SELLS: {} \t => {}{}'.format(sell_count, total_sold, CURRENCY)) print('INPUT \t\t => {}{}'.format(highest_amount_entered, CURRENCY)) return (total_bought, total_sold, highest_amount_entered)
def main(): # 读取文件 file_names = os.listdir(RE_PATH) # file_names.remove(".DS_Store") for file_name in file_names: names = file_name.split("_") _type = names[1] print(names) exchange_name = names[2] symbol_name = names[3].replace(".txt", "") if _type == "trade": obj = Trade(exchange_name, symbol_name) elif _type == "orderbook": obj = OrderBook(exchange_name, symbol_name) # 插入数据 with open(RE_PATH + file_name) as f: for line in f.readlines(): line = json.loads(line) documents = copy.deepcopy(line) for document in documents: try: obj.collection.replace_one(filter=document, replacement=document, upsert=True) except Exception: with open(obj.collection_name + ".txt", "a") as f: f.write(json.dumps(document)) f.write("\n")
def test_partially_filled(self): # Same size orders should fill each other completely buy = createBuy(quantity=200) sell = createSell() trade = Trade.create(buy, sell) assert trade assert trade.quantity == sell.quantity assert buy.unfilled() == 100 assert sell.unfilled() == 0 sell = createSell(quantity=300) trade = Trade.create(buy, sell) assert trade assert trade.quantity == 100 assert buy.unfilled() == 0 assert sell.unfilled() == 200
def main(): """ """ parser = argparse.ArgumentParser(description="生成某一天kline") parser.add_argument("--day", "-d", help="日期") parser.add_argument("--exchange", "-e", help="交易所名称", type=str) parser.add_argument("--symbol", "-s", help="标的", type=str) args = parser.parse_args() day = args.day exchange = args.exchange symbol = args.symbol if not day or not exchange or not symbol: print("Invalid args!!!") print( "example:\n\npython db/insert_data/generate_last_day_klines.py -d 2012-12-2 -e huobi -s btcusdt" ) return begin_timestamp = int( datetime.datetime.strptime(day, "%Y-%m-%d").timestamp() * 1000) kline = Kline(exchange, symbol) #数据库K线表读写 trade = Trade(exchange, symbol) #数据库逐笔成交表读写 update_one_day_klines(trade, kline, begin_timestamp)
def when_sell(self): if len(self.tickers) != 30: return False if (self.buys - self.sells) == 0: return False # make sure we dont sell with loss last_buy = Trade.select().where(Trade.test == self.test, Trade.currency == self.ticker.currency, Trade.type == 'buy').order_by(Trade.date.desc()).get() (profit, profit_pct) = calc_diff(last_buy.price, self.ticker.price) self.profit_pct = profit_pct self.profit = (last_buy.quantity * self.ticker.price) - \ (last_buy.quantity * last_buy.price) # sell at loss when -10% # if profit_pct <= -10: # return True if last_buy.price >= self.ticker.price or profit_pct <= 5: return False if profit_pct >= 5: return True return self.diff_pct >= 2.75
def sec_tops(secs): lt = {} bb = {} ba = {} for sec in secs: # Last traded price t = Trade.query(Trade.security == sec).order(-Trade.timestamp) t = list(t) if len(t) > 0: lt[sec.key.id()] = t[0].price else: lt[sec.key.id()] = 0 # Best bid t = Order.query(Order.security == sec, Order.buysell == 'Buy', Order.active == True).order(-Order.price) t = list(t) if len(t) > 0: bb[sec.key.id()] = t[0].price else: bb[sec.key.id()] = 0 # Best ask t = Order.query(Order.security == sec, Order.buysell == 'Sell', Order.active == True).order(Order.price) t = list(t) if len(t) > 0: ba[sec.key.id()] = t[0].price else: ba[sec.key.id()] = 0 tops = {'lt':lt, 'bb':bb, 'ba':ba} return tops
def start(): # remove all previous test trades test_trades = Trade.select().where(Trade.test == True) for test_trade in test_trades: test_trade.delete_instance() for symbol in SYMBOLS: tickers = reverse(Ticker.select().where( Ticker.currency == symbol, Ticker.epoch > 1614766446).order_by(-Ticker.epoch)) for i in range(len(tickers)): last_30_tickers = reverse(get_last_x_items(tickers, i, 30)) if len(last_30_tickers) < 30: continue strategy = Strategy(last_30_tickers, test=True) if strategy.when_buy(): test_buy(symbol, strategy.ticker) if strategy.when_sell(): test_sell(symbol, strategy.ticker) wallet(test=True)
def new_trade_csv(): ntcForm = NewTradeCsvForm() if ntcForm.validate_on_submit(): for row in ntcForm.csv.data.splitlines(): split = [i.title() for i in row.split(',')] t_moves = split[11:] for i in range(4 - len(t_moves)): t_moves.append(None) species_list = [i[0].split(',')[1].title() for i in national_dex] data = { 'dex_no': species_list.index(split[0]) + 1, 'species': split[0], 'male': split[1] == 'True', 'female': split[2] == 'True', 'nature': split[3], 'ability': split[4], 'iv_hp': split[5], 'iv_atk': split[6], 'iv_def': split[7], 'iv_spa': split[8], 'iv_spd': split[9], 'iv_spe': split[10], 'move1': t_moves[0], 'move2': t_moves[1], 'move3': t_moves[2], 'move4': t_moves[3] } trade = Trade(owner=g.user, data=data) td = trade.__dict__.copy() del td['_sa_instance_state'] if Trade.query.filter_by(**td).first() is None: db.session.add(trade) db.session.commit() flash('Your {} was successfully added'.format(split[0]), 'success') status = '{0} just added a {1} {2} {3} ({4}) {5}'.format( g.user.nickname, trade.nature, trade.ability, trade.species, trade.ivSpread(), url_for('user', nickname=g.user.nickname, _external=True) ) api.PostUpdate(status) else: flash('You have already added this trade', 'error') return redirect(request.args.get('next') or url_for('user', nickname=g.user.nickname))
def test_items_displayed_do_not_include_items_in_completed_trades(self): user1 = User(username='******', email='*****@*****.**', password='******') user2 = User(username='******', email='*****@*****.**', password='******') sheetmusic = Sheetmusic(composer='composer1', title='piece 2') item = Item(user=user1, sheetmusic_id=sheetmusic.id, condition='Clean') self.assertEqual(user1.items, user1.get_available_items()) trade = Trade(item_to=item, user_to=user1, user_from=user2) self.assertEqual(user1.items, user1.get_available_items()) trade.completed = True trade.rejected = True self.assertEqual(user1.items, user1.get_available_items()) trade.rejected = False self.assertNotEqual(user1.items, user1.get_available_items())
def test_do_not_allow_user_to_trade_with_self(self): user_from = User('*****@*****.**', 'abe', '1234') user_to = User('*****@*****.**', 'lincoln', '4321') trade = Trade(user_from_id=user_from.id, user_to_id=user_from.id) self.db.add(trade) with self.assertRaises(IntegrityError): self.db.commit()
def sell(currency): symbol = '{}{}'.format(currency, CURRENCY) balance = get_balance(currency) quantity = get_quantity(currency) if quantity > 0: info = client.get_symbol_info(symbol=symbol) stepSize = float(info['filters'][2]['stepSize']) precision = int(round(-math.log(stepSize, 10), 0)) if quantity >= balance: quantity = balance order = client.create_order(symbol=symbol, side=Client.SIDE_SELL, type=Client.ORDER_TYPE_MARKET, quantity=round_down(quantity, precision)) print(order) quantity = 0 fee = 0 for fill in order['fills']: fee += float(fill['commission']) quantity += float(fill['qty']) price = float(order['fills'][0]['price']) total = float(order['cummulativeQuoteQty']) total = total - fee now = datetime.now() Trade.create(currency=currency, quantity=quantity, price=price, fee=fee, total=total, type='sell', date=now, epoch=now.timestamp(), test=False) if TELEGRAM_TOKEN and TELEGRAM_PRIVATE_CHAT_ID: send_private_telegram('{} {} SOLD FOR {}{}'.format( quantity, currency, round(total, 2), CURRENCY))
def on_trade(self, msg): if not self.is_ready: self.process_later.append(msg) return trade = { "price": msg.get('MDEntryPx'), "symbol": msg.get('Symbol'), "size": msg.get('MDEntrySize'), "trade_date": msg.get('MDEntryDate'), "trade_time": msg.get('MDEntryTime'), "order_id": msg.get('OrderID'), "side": msg.get('Side'), "counter_order_id": msg.get('SecondaryOrderID'), "id": msg.get('TradeID'), "buyer_id": msg.get('MDEntryBuyerID'), "seller_id": msg.get('MDEntrySellerID'), "buyer_username": msg.get('MDEntryBuyer'), "seller_username": msg.get('MDEntrySeller'), } Trade.create(self.db_session, trade) # BTC BRL price_currency = self.symbol[3:] size_currency = self.symbol[:3] if price_currency not in self.volume_dict: self.volume_dict[price_currency] = 0 if size_currency not in self.volume_dict: self.volume_dict[size_currency] = 0 volume_price = int( msg.get('MDEntryPx') * msg.get('MDEntrySize') / 1.e8) volume_size = msg.get('MDEntrySize') self.volume_dict[price_currency] += volume_price self.volume_dict[size_currency] += volume_size self.volume_dict['MDEntryType'] = '4' signal_publish_md_status('MD_STATUS', self.volume_dict) self.inst_status.push_trade(trade)
def readmail(volume): time.sleep(1.5) m = imaplib.IMAP4_SSL(imap) m.login(user, pwd) m.select('"' + folder + '"') resp, items = m.search(None, "NOT SEEN SUBJECT tradingview") items = items[0].split() for emailid in items: resp, data = m.fetch(emailid, "(RFC822)") email_body = data[0][1] mail = email.message_from_bytes(email_body) ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') nonce = generate_nonce() direction = mail['Subject'].split()[3] if direction == "Buy": signal = "0" else: signal = "1" pair = mail['Subject'].split()[2] try: if "Close" not in direction: setup = Trade.get_or_create(pair) m.store(emailid, '+FLAGS', '\Seen') log(st + ' ' + direction + ' Triggered on ' + pair) if hedging == "0": if setup.nonce is not None: cnr(signal, volume, pair, nonce) else: trade(signal, volume, pair, nonce) else: trade(signal, volume, pair, nonce) # Close Trade else: direction = mail['Subject'].split()[4] setup = Trade.find(pair) if setup is not None: if setup.signal == direction: m.store(emailid, '+FLAGS', '\Seen') close(signal, volume, pair) log(st + " Closed trade on " + pair) except Exception as e: log(e)
def buy(currency, input=ORDER_INPUT): symbol = '{}{}'.format(currency, CURRENCY) order_price = float(input) trades = client.get_recent_trades(symbol=symbol) price = float(trades[0]['price']) quantity = order_price / price info = client.get_symbol_info(symbol=symbol) stepSize = float(info['filters'][2]['stepSize']) precision = int(round(-math.log(stepSize, 10), 0)) order = client.create_order(symbol=symbol, side=Client.SIDE_BUY, type=Client.ORDER_TYPE_MARKET, quantity=(round(quantity, precision))) print(order) quantity = 0 commission = 0 for fill in order['fills']: commission += float(fill['commission']) quantity += float(fill['qty']) quantity = quantity - commission price = float(order['fills'][0]['price']) total = float(order['cummulativeQuoteQty']) fee = commission * price now = datetime.now() Trade.create(currency=currency, quantity=quantity, price=price, fee=fee, total=total, type='buy', date=now, epoch=now.timestamp(), test=False) if TELEGRAM_TOKEN and TELEGRAM_PRIVATE_CHAT_ID: send_private_telegram('{} {} BOUGHT FOR {}{}'.format( quantity, currency, round(total, 2), CURRENCY))
def add_trade_by_form(): i = 0 not_added = [] results = request.json category = Category.query.filter( Category.name == results["category"]).first() new_trade = Trade(category_id=category.id, name=results["name"].capitalize(), cost_per_hour=results["cost"]) db.session.add(new_trade) db.session.commit() return results
def generate_trade_history(page_size=None, offset=None, sort_column=None, sort_order='ASC'): trades = Trade.get_last_trades(page_size, offset, sort_column, sort_order) trade_list = [] for trade in trades: trade_list.append([ trade.id, trade.symbol, trade.side, trade.price, trade.size, trade.buyer_username, trade.seller_username, trade.created ]) return trade_list
def get_order_trades(self, symbol, order_id): """ Get all of the trades that have been generated by the given order associated with API_KEY - Requires authentication. @param symbol string: pair symbol i.e tBTCUSD @param order_id string: id of the order @return Array <models.Trade> """ endpoint = "auth/r/order/{}:{}/trades".format(symbol, order_id) raw_trades = self.post(endpoint) return [Trade.from_raw_rest_trade(rt) for rt in raw_trades]
def new_trade(): ntForm = NewTradeForm() if ntForm.validate_on_submit(): trade = Trade(owner=g.user, data=ntForm.data) td = trade.__dict__.copy() del td['_sa_instance_state'] if Trade.query.filter_by(**td).first() is None: db.session.add(trade) db.session.commit() flash('Your {} was successfully added'.format(ntForm.species.data.split(',')[1]), 'success') status = '{0} just added a {1} {2} {3} ({4}) {5}'.format( g.user.nickname, trade.nature, trade.ability, trade.species, trade.ivSpread(), url_for('user', nickname=g.user.nickname, _external=True) ) api.PostUpdate(status) else: flash('You have already added this trade', 'error') return redirect(request.args.get('next') or url_for('user', nickname=g.user.nickname))
def generate_trade_history(page_size = None, offset = None, sort_column = None, sort_order='ASC'): trades = Trade.get_last_trades(page_size, offset, sort_column, sort_order) trade_list = [] for trade in trades: trade_list.append([ trade.id, trade.symbol, trade.side, trade.price, trade.size, trade.buyer_username, trade.seller_username, trade.created ]) return trade_list
def get(self): """ Returns a JSON containing the Trades in the system. Fields returned are filtered by the get parameter 'f'. Trades are filtered by timestamp: 'timestamp_gt': All the trades with a timestamp greater than 'timestamp_lt': All the trades with a timestamp lesser than """ self.response.headers['Content-Type'] = 'application/json' fields = self.request.GET.get('f') timestamp_gt = self.request.GET.get('timestamp_gt') timestamp_lt = self.request.GET.get('timestamp_lt') fields = fields.split(',') if fields else None result = Trade.query_by_timestamp(timestamp_lt, timestamp_gt) data = [trade.serialize(fields=fields) for trade in result] self.response.write(json.dumps(data, indent=4))
def generate_trade_history(session, page_size = None, offset = None, sort_column = None, sort_order='ASC', show_username=False): trades = Trade.get_last_trades(session, page_size, offset, sort_column, sort_order) trade_list = [] for trade in trades: rec = [ trade.id, trade.symbol, trade.side, trade.price, trade.size, trade.buyer_id, trade.seller_id, trade.created ] if show_username: rec.append(trade.buyer_username) rec.append(trade.seller_username) trade_list.append(rec) return trade_list
def test_example_csv(self): """ Date,Symbol,TimeStamp,QuoteCount,TradeCount,OpenPx,ClosePx,HighPx,LowPx 20130719,LFZ,2013-07-19 08:47:00.000457891,304,24,6387.0000000, 6386.5000000,6387.0000000,6386.0000000 """ load_from_dataset('tests/example.csv') trade = Trade.query().get() self.assertEqual(trade.date, datetime.date(2013, 7, 19)) self.assertEqual(trade.symbol, 'LFZ') self.assertEqual( trade.timestamp, datetime.datetime(2013, 7, 19, 8, 47, 0) ) self.assertEqual(trade.timestamp_nanoseconds, 457891) self.assertEqual(trade.quotecount, 304) self.assertEqual(trade.tradecount, 24) self.assertEqual(trade.openpx, 6387.0000000) self.assertEqual(trade.closepx, 6386.5000000) self.assertEqual(trade.highpx, 6387.0000000) self.assertEqual(trade.lowpx, 6386.0000000)
def get_last_trades(self): """" get_last_trades. """ return Trade.get_last_trades(self.db_session)
def test_trades_are_deleted(self): load_from_dataset('tests/example.csv') self.assertEqual(Trade.query().count(), 1) delete_all() self.assertEqual(Trade.query().count(), 0)
def get_last_trades(self): """" get_last_trades. """ return Trade.get_last_trades()
def trade_add(request): goods_top = Trade.objects.values('goods__id','goods__title').annotate(goods_count=Count('goods')).order_by('-goods_count')[:10] price1 = 0 results = [] if request.method == 'POST': # If the form has been submitted... form = TradeForm(request.POST) # A form bound to the POST data if form.is_valid(): # All validation rules pass # Process the data in form.cleaned_data # ... #return HttpResponseRedirect('/thanks/') # Redirect after POST #results = GClass.objects.filter(title__icontains=form.cleaned_data['goodstitle']) isOldTrade = False if int(form.cleaned_data["trade_pk"]) > 0: isOldTrade = True shop1 = None if int(form.cleaned_data["shop_pk"]) > 0: shop1 = Shop.objects.get(pk=form.cleaned_data["shop_pk"]) else: shop1 = Shop(title=form.cleaned_data["shop"], type='mag') shop1.save() #gclass1 = None #if int(form.cleaned_data["gclass_pk"]) > 0: # gclass1 = GClass.objects.get(pk=form.cleaned_data["gclass_pk"]) #else: # gclass1 = GClass(title=form.cleaned_data["gclass"], section=GSection.objects.get(pk=1)) #TODO GSection # gclass1.save() goods1 = None if int(form.cleaned_data["gtitle_pk"]) > 0: goods1 = Goods.objects.get(pk=form.cleaned_data["gtitle_pk"]) goods1.title = form.cleaned_data["gtitle"] goods1.ed = form.cleaned_data["ed"] #goods1.gclass = gclass1 goods1.save() else: goods1 = Goods(title=form.cleaned_data["gtitle"], ed=form.cleaned_data["ed"]) goods1.save() price1 = "%.2f" % ( float(form.cleaned_data['cost']) / float(form.cleaned_data['amount']) ) if isOldTrade: trade1 = Trade.objects.get(pk=form.cleaned_data["trade_pk"]) else: trade1 = Trade() trade1.user = request.user trade1.shop = shop1 trade1.goods = goods1 trade1.time = form.cleaned_data["time"] trade1.amount = form.cleaned_data["amount"] trade1.price = price1 trade1.cost = form.cleaned_data["cost"] trade1.currency = form.cleaned_data["currency"] trade1.spytrade = form.cleaned_data["spytrade"] trade1.save() return HttpResponseRedirect("/") else: data = {'time': datetime.datetime.now, 'trade_pk': '0', 'shop_pk': '0', 'gclass_pk': '0', 'gtitle_pk': '0' } form = TradeForm(initial=data) # An unbound form return render_to_response('trade_add.html', {'price': price1, 'results': results, 'form': form, 'goods_top': goods_top}, context_instance=RequestContext(request))
def get_trades(self, symbol, since): """" get_trades. """ return Trade.get_trades(self.db_session, symbol, since)
def match(self, session, order, order_matcher_disabled=False): other_side = [] self_side = [] if order.is_buy: self_side = self.buy_side other_side = self.sell_side elif order.is_sell: other_side = self.buy_side self_side = self.sell_side execution_reports = [] trades_to_publish = [] execution_side = '1' if order.is_buy else '2' rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, rpt_order.toJson() ) ) is_last_match_a_partial_execution_on_counter_order = False execution_counter = 0 number_of_filled_counter_market_orders = 0 if not order_matcher_disabled: for execution_counter in xrange(0, len(other_side) + 1): if execution_counter == len(other_side): break # workaround to make the execution_counter be counted until the last order. if not order.leaves_qty > 0: break counter_order = other_side[execution_counter] if not order.has_match(counter_order): break # check for self execution if order.account_id == counter_order.account_id: # self execution.... let's cancel the counter order counter_order.cancel_qty( counter_order.leaves_qty ) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) # go to the next order is_last_match_a_partial_execution_on_counter_order = False continue # Get the desired executed price and qty, by matching against the counter_order executed_qty = order.match( counter_order, order.leaves_qty) if counter_order.type == '1': # Market Order executed_price = order.price number_of_filled_counter_market_orders += 1 else: executed_price = counter_order.price # let's get the available qty to execute on the order side available_qty_on_order_side = order.get_available_qty_to_execute(session, '1' if order.is_buy else '2', executed_qty, executed_price ) qty_to_cancel_from_order = 0 if available_qty_on_order_side < executed_qty: # ops ... looks like the order.user didn't have enough to execute the order executed_qty = available_qty_on_order_side # cancel the remaining qty qty_to_cancel_from_order = order.leaves_qty - executed_qty # check if the order got fully cancelled if not executed_qty: order.cancel_qty( qty_to_cancel_from_order ) cancel_rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, cancel_rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, cancel_rpt_order.toJson() ) ) break # let's get the available qty to execute on the counter side available_qty_on_counter_side = counter_order.get_available_qty_to_execute(session, '1' if counter_order.is_buy else '2', executed_qty, executed_price ) qty_to_cancel_from_counter_order = 0 if available_qty_on_counter_side < executed_qty: if qty_to_cancel_from_order: qty_to_cancel_from_order -= executed_qty - available_qty_on_order_side # ops ... looks like the counter_order.user didn't have enough to execute the order executed_qty = available_qty_on_counter_side # cancel the remaining qty qty_to_cancel_from_counter_order = counter_order.leaves_qty - executed_qty # check if the counter order was fully cancelled due the lack if not executed_qty: # just cancel the counter order, and go to the next order. counter_order.cancel_qty( qty_to_cancel_from_counter_order ) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) # go to the next order is_last_match_a_partial_execution_on_counter_order = False continue # lets perform the execution if executed_qty: order.execute( executed_qty, executed_price ) counter_order.execute(executed_qty, executed_price ) trade = Trade.create(session, order, counter_order, self.symbol, executed_qty, executed_price ) trades_to_publish.append(trade) rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, rpt_order.toJson() ) ) rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, rpt_counter_order.toJson() ) ) def generate_email_subject_and_body( session, order, trade ): from json import dumps from pyblinktrade.json_encoder import JsonEncoder from models import Currency qty_currency = order.symbol[:3] formatted_qty = Currency.format_number( session, qty_currency, trade.size / 1.e8 ) price_currency = order.symbol[3:] formatted_price = Currency.format_number( session, price_currency, trade.price / 1.e8 ) formatted_total_price = Currency.format_number( session, price_currency, trade.size/1.e8 * trade.price/1.e8 ) email_subject = 'E' email_template = "order-execution" email_params = { 'username': order.user.username, 'order_id': order.id, 'trade_id': trade.id, 'side': order.side, 'executed_when': trade.created, 'qty': formatted_qty, 'price': formatted_price, 'total': formatted_total_price } return email_subject, email_template, dumps(email_params, cls=JsonEncoder) email_data = generate_email_subject_and_body(session, counter_order, trade) UserEmail.create( session = session, user_id = counter_order.account_id, broker_id = counter_order.broker_id, subject = email_data[0], template= email_data[1], language= counter_order.email_lang, params = email_data[2]) # # let's do the partial cancels # # Cancel the qty from the current order if qty_to_cancel_from_order: order.cancel_qty(qty_to_cancel_from_order) # generate a cancel report cancel_rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, cancel_rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, cancel_rpt_order.toJson() ) ) if qty_to_cancel_from_counter_order: counter_order.cancel_qty(qty_to_cancel_from_counter_order) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.leaves_qty > 0: is_last_match_a_partial_execution_on_counter_order = True md_entry_type = '0' if order.is_buy else '1' counter_md_entry_type = '1' if order.is_buy else '0' # let's include the order in the book if the order is not fully executed. if order.leaves_qty > 0: insert_pos = bisect.bisect_right(self_side, order) self_side.insert( insert_pos, order ) if order.type == '2': # Limited orders go to the book. MarketDataPublisher.publish_new_order( self.symbol, md_entry_type , insert_pos, order) # don't send the first execution report (NEW) if the order was fully cancelled if order.is_cancelled and order.cum_qty == 0: execution_reports.pop(0) # Publish all execution reports for user_id, execution_report in execution_reports: TradeApplication.instance().publish( user_id, execution_report ) # Publish Market Data for the counter order if execution_counter: if is_last_match_a_partial_execution_on_counter_order: del other_side[0: execution_counter-1] MarketDataPublisher.publish_executions( self.symbol, counter_md_entry_type, execution_counter - 1 - number_of_filled_counter_market_orders, other_side[0] ) else: del other_side[0: execution_counter] MarketDataPublisher.publish_executions( self.symbol, counter_md_entry_type, execution_counter - number_of_filled_counter_market_orders ) if trades_to_publish: MarketDataPublisher.publish_trades(self.symbol, trades_to_publish) return ""
def test_default_dataset_can_be_loaded(self): load_from_dataset() self.assertEqual(Trade.query().count(), 512)
def __init__(self, opt): handlers = [ (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler), (r'/_webhook/verification_form', VerificationWebHookHandler), (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler), (r'/process_deposit(.*)', ProcessDepositHandler), (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler) ] settings = dict( cookie_secret='cookie_secret' ) tornado.web.Application.__init__(self, handlers, **settings) self.replay_logger = logging.getLogger("REPLAY") self.replay_logger.setLevel(logging.INFO) self.replay_logger.addHandler(input_log_file_handler) self.replay_logger.info('START') self.log_start_data() from models import ENGINE, db_bootstrap self.db_session = scoped_session(sessionmaker(bind=ENGINE)) db_bootstrap(self.db_session) self.zmq_context = zmq.Context() self.trade_in_socket = self.zmq_context.socket(zmq.REQ) self.trade_in_socket.connect(opt.trade_in) self.application_trade_client = TradeClient( self.zmq_context, self.trade_in_socket) self.application_trade_client.connect() instruments = self.application_trade_client.getSecurityList() self.md_subscriber = {} for instrument in instruments: symbol = instrument['Symbol'] self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self) self.md_subscriber[symbol].subscribe( self.zmq_context, options.trade_pub, self.application_trade_client) last_trade_id = Trade.get_last_trade_id() trade_list = self.application_trade_client.getLastTrades(last_trade_id) for trade in trade_list: msg = dict() msg['id'] = trade[0] msg['symbol'] = trade[1] msg['side'] = trade[2] msg['price'] = trade[3] msg['size'] = trade[4] msg['buyer_username'] = trade[5] msg['seller_username'] = trade[6] msg['created'] = trade[7] msg['trade_date'] = trade[7][:10] msg['trade_time'] = trade[7][11:] msg['order_id'] = trade[8] msg['counter_order_id'] = trade[9] Trade.create( self.db_session, msg) all_trades = Trade.get_all_trades(self.db_session) for t in all_trades: trade_info = dict() trade_info['price'] = t.price trade_info['size'] = t.size trade_info['trade_date'] = t.created.strftime('%Y-%m-%d') trade_info['trade_time'] = t.created.strftime('%H:%M:%S') self.md_subscriber[ t.symbol ].inst_status.push_trade(trade_info) for symbol, subscriber in self.md_subscriber.iteritems(): subscriber.ready() self.connections = {} self.heart_beat_timer = tornado.ioloop.PeriodicCallback( self.send_heartbeat_to_trade, 30000) self.heart_beat_timer.start()
def __init__(self, opt, instance_name): self.options = opt self.instance_name = instance_name handlers = [ (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler), (r'/_webhook/verification_form', VerificationWebHookHandler), (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler), (r'/process_deposit(.*)', ProcessDepositHandler), (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler) ] settings = dict( cookie_secret='cookie_secret' ) tornado.web.Application.__init__(self, handlers, **settings) self.allowed_origins = json.loads(self.options.allowed_origins) self.allow_all_origins = self.allowed_origins[0] == '*' input_log_file_handler = logging.handlers.TimedRotatingFileHandler( os.path.expanduser(self.options.gateway_log), when='MIDNIGHT') formatter = logging.Formatter('%(asctime)s - %(message)s') input_log_file_handler.setFormatter(formatter) self.replay_logger = logging.getLogger(self.instance_name) self.replay_logger.setLevel(logging.INFO) self.replay_logger.addHandler(input_log_file_handler) ch = logging.StreamHandler(sys.stdout) ch.setLevel(logging.DEBUG) ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) self.replay_logger.addHandler(ch) self.replay_logger.info('START') self.log_start_data() from models import Base, db_bootstrap db_engine = self.options.sqlalchemy_engine + ':///' +\ os.path.expanduser(self.options.sqlalchemy_connection_string) engine = create_engine( db_engine, echo=self.options.db_echo) Base.metadata.create_all(engine) self.db_session = scoped_session(sessionmaker(bind=engine)) db_bootstrap(self.db_session) self.zmq_context = zmq.Context() self.trade_in_socket = self.zmq_context.socket(zmq.REQ) self.trade_in_socket.connect(self.options.trade_in) self.application_trade_client = TradeClient( self.zmq_context, self.trade_in_socket) self.application_trade_client.connect() self.security_list = self.application_trade_client.getSecurityList() self.md_subscriber = {} for instrument in self.security_list.get('Instruments'): symbol = instrument['Symbol'] self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self) self.md_subscriber[symbol].subscribe( self.zmq_context, self.options.trade_pub, self.application_trade_client) last_trade_id = Trade.get_last_trade_id(self.db_session) trade_list = self.application_trade_client.getLastTrades(last_trade_id) for trade in trade_list: msg = dict() msg['id'] = trade[0] msg['symbol'] = trade[1] msg['side'] = trade[2] msg['price'] = trade[3] msg['size'] = trade[4] msg['buyer_id'] = trade[5] msg['seller_id'] = trade[6] msg['buyer_username'] = trade[7] msg['seller_username'] = trade[8] msg['created'] = trade[9] msg['trade_date'] = trade[9][:10] msg['trade_time'] = trade[9][11:] msg['order_id'] = trade[10] msg['counter_order_id'] = trade[11] Trade.create( self.db_session, msg) all_trades = Trade.get_all_trades(self.db_session) for t in all_trades: trade_info = dict() trade_info['price'] = t.price trade_info['size'] = t.size trade_info['trade_date'] = t.created.strftime('%Y-%m-%d') trade_info['trade_time'] = t.created.strftime('%H:%M:%S') self.md_subscriber[ t.symbol ].inst_status.push_trade(trade_info) for symbol, subscriber in self.md_subscriber.iteritems(): subscriber.ready() self.connections = {} self.heart_beat_timer = tornado.ioloop.PeriodicCallback( self.send_heartbeat_to_trade, 30000) self.heart_beat_timer.start()
def match_orders(sec, buysell): """Match orders in cross""" # Get buy and sell lists b = Order.query(Order.security == sec, Order.buysell == 'Buy', Order.active == True, ancestor=sec.key).order(-Order.price, Order.timestamp) s = Order.query(Order.security == sec, Order.buysell == 'Sell', Order.active == True, ancestor=sec.key).order(Order.price, Order.timestamp) b = list(b) s = list(s) # Match orders until market uncrosses bn = 0 sn = 0 while(1): if bn + 1 > len(b): break if sn + 1 > len(s): break if b[bn].price >= s[sn].price: t = Trade() t.timestamp = datetime.utcnow() t.buy_user = b[bn].user t.sell_user = s[sn].user t.security = b[bn].security if buysell == "Buy": t.price = s[sn].price else: t.price = b[bn].price b[bn] = b[bn].key.get() s[sn] = s[sn].key.get() b_ptf = Portfolio.query(Portfolio.user == b[bn].user).get() s_ptf = Portfolio.query(Portfolio.user == s[sn].user).get() if b[bn].volume > s[sn].volume: t.volume = s[sn].volume b[bn].volume += -s[sn].volume s[sn].active = False b_ptf.points += s[sn].volume s_ptf.points += s[sn].volume b[bn].put() s[sn].put() sn += 1 elif b[bn].volume < s[sn].volume: t.volume = b[bn].volume s[sn].volume += -b[bn].volume b[bn].active = False b_ptf.points += b[bn].volume s_ptf.points += b[bn].volume b[bn].put() s[sn].put() bn += 1 elif b[bn].volume == s[sn].volume: t.volume = b[bn].volume b[bn].active = False s[sn].active = False b_ptf.points += b[bn].volume s_ptf.points += b[bn].volume b[bn].put() s[sn].put() bn += 1 sn += 1 b_ptf.put() s_ptf.put() t.put() flash(u'Trade %s successfully completed.' % t.key.id(), 'success') continue break