def update_email(api_key: str, email: str, response: Response): email_obj = ndb.Key("UserEmail", api_key).get() if email_obj is None: email_obj = UserEmail(id=api_key, email=email) response.status_code = status.HTTP_201_CREATED else: email_obj.email = email response.status_code = status.HTTP_200_OK email_obj.put()
def testUpdate(self): self.user_a.upate('*****@*****.**', 'Bar Foy') self.assertEqual('Bar Foy', self.user_a.name) self.assertTrue(self.user_a.has_email()) self.assertEqual(self.user_a, UserEmail.find_user('*****@*****.**')) self.user_b.upate('*****@*****.**', 'Foo Bar') self.assertEqual('Foo Bar', self.user_b.name) self.assertEqual('*****@*****.**', self.user_b.get_default_email()) self.assertEqual(self.user_b, UserEmail.find_user('*****@*****.**'))
def send(request): email = request.POST.get('mail', None) if email: user_emails = UserEmail.objects.filter(email=email) if user_emails.count() == 0: user_email = UserEmail(user=request.user, email=email) user_email.save() try: send_mail( 'Letter', 'msg', '*****@*****.**', [request.POST.get('mail', '')], fail_silently=False, html_message=request.POST.get('html') ) return HttpResponse('200') except: return HttpResponse('500')
def setUp(self): self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() self.user_a = User() self.user_a.put() self.user_b = User() self.user_b.name = 'Foo Bar' self.user_b.clientID = 'C123' self.user_b.put() self.setting = UserSettingKey() self.setting.name = 'SEND_EMAIL' self.setting.description = 'Acceptance to receiv E-mail' self.setting.values = ['0', '1'] self.setting.put() self.user_setting = UserSetting() self.user_setting.setting_key = self.setting.key self.user_setting.user = self.user_b.key self.user_setting.value = '0' self.user_setting.put() self.email_a = UserEmail() self.email_a.email = '*****@*****.**' self.email_a.is_activated = False self.email_a.is_default = False self.email_a.user = self.user_b.key self.email_a.put() self.email_b = UserEmail() self.email_b.email = '*****@*****.**' self.email_b.is_activated = True self.email_b.is_default = True self.email_b.user = self.user_b.key self.email_b.put()
def testDefaultEmailConsistancy(self): self.assertEqual(None, self.user_a.get_default_email()) self.assertEqual('*****@*****.**', self.user_b.get_default_email()) UserEmail.create_or_update(self.user_a, '*****@*****.**', True) UserEmail.create_or_update(self.user_b, '*****@*****.**', True) user_a_emails = UserEmail.gql("WHERE user = :1", self.user_a.key).fetch() user_b_emails = UserEmail.gql("WHERE user = :1", self.user_b.key).fetch() self.assertEqual(1, len(user_a_emails)) self.assertTrue(user_a_emails[0].is_default) self.assertEqual(3, len(user_b_emails)) for email in user_b_emails: if '*****@*****.**' == email.email: self.assertTrue(email.is_default) else: self.assertFalse(email.is_default)
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, order, trade) UserEmail.create( session = session, user_id = order.account_id, broker_id = order.broker_id, subject = email_data[0], template= email_data[1], language= order.email_lang, params = email_data[2]) 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 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 get(self): return UserEmail(id="123abc", email="*****@*****.**")
class Test(unittest.TestCase): def setUp(self): self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() self.user_a = User() self.user_a.put() self.user_b = User() self.user_b.name = 'Foo Bar' self.user_b.clientID = 'C123' self.user_b.put() self.setting = UserSettingKey() self.setting.name = 'SEND_EMAIL' self.setting.description = 'Acceptance to receiv E-mail' self.setting.values = ['0', '1'] self.setting.put() self.user_setting = UserSetting() self.user_setting.setting_key = self.setting.key self.user_setting.user = self.user_b.key self.user_setting.value = '0' self.user_setting.put() self.email_a = UserEmail() self.email_a.email = '*****@*****.**' self.email_a.is_activated = False self.email_a.is_default = False self.email_a.user = self.user_b.key self.email_a.put() self.email_b = UserEmail() self.email_b.email = '*****@*****.**' self.email_b.is_activated = True self.email_b.is_default = True self.email_b.user = self.user_b.key self.email_b.put() def tearDown(self): self.testbed.deactivate() def testGetSettings(self): self.assertEqual(0, len(self.user_a.get_settings())) settings = self.user_b.get_settings() self.assertEqual(1, len(settings)) self.assertEqual('SEND_EMAIL', settings[0].setting_key.get().name) def testUpdateSettings(self): self.user_a.update_setting(self.setting, '1') self.assertEqual('0', self.user_setting.value) self.user_b.update_setting(self.setting, '1') self.assertEqual('1', self.user_setting.value) def testUpdate(self): self.user_a.upate('*****@*****.**', 'Bar Foy') self.assertEqual('Bar Foy', self.user_a.name) self.assertTrue(self.user_a.has_email()) self.assertEqual(self.user_a, UserEmail.find_user('*****@*****.**')) self.user_b.upate('*****@*****.**', 'Foo Bar') self.assertEqual('Foo Bar', self.user_b.name) self.assertEqual('*****@*****.**', self.user_b.get_default_email()) self.assertEqual(self.user_b, UserEmail.find_user('*****@*****.**')) def testHasEmail(self): self.assertFalse(self.user_a.has_email()) self.assertTrue(self.user_b.has_email()) def testDefaultEmailConsistancy(self): self.assertEqual(None, self.user_a.get_default_email()) self.assertEqual('*****@*****.**', self.user_b.get_default_email()) UserEmail.create_or_update(self.user_a, '*****@*****.**', True) UserEmail.create_or_update(self.user_b, '*****@*****.**', True) user_a_emails = UserEmail.gql("WHERE user = :1", self.user_a.key).fetch() user_b_emails = UserEmail.gql("WHERE user = :1", self.user_b.key).fetch() self.assertEqual(1, len(user_a_emails)) self.assertTrue(user_a_emails[0].is_default) self.assertEqual(3, len(user_b_emails)) for email in user_b_emails: if '*****@*****.**' == email.email: self.assertTrue(email.is_default) else: self.assertFalse(email.is_default) def testFindByEmail(self): user = User.find_by_email('*****@*****.**') self.assertEqual(self.user_b, user) user = User.find_by_email('*****@*****.**') self.assertEqual(self.user_b, user) user = User.find_by_email('*****@*****.**') self.assertEqual(None, user) def testClinet(self): self.assertEqual(self.user_b, User.client('C123')) user = User.client('C001') self.assertNotEqual(None, user) self.assertEqual('C001', user.clientID)