#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import datetime
import sys
import os
from sqlalchemy import create_engine
import pandas as pd
import urllib
import getopt
import re
import logging
logging.basicConfig(level=logging.INFO,filename='report_runlog.log',filemode='a',
format='%(asctime)s-%(levelname)5s: %(message)s')
def usage():
print '-s, --server\t\tServer name or ip address which DB hosts'
print '-d, --database\t\tThe database name in the DB server'
print '-u, --user\t\tThe user name to access the database'
print '-p, --password\t\tThe password to access the database'
print '-t, --date\t\tThe date to search in the database, format is 20180102. default: Yesterday)'
print '-a, --account\t\tThe account to search in the database. default: "F190402","F190436"'
print '-f, --filename\t\tSpecify the report name. default: "report_now.xlsx"'
print '-h, --help\t\tprint this screen'
def getOption():
global server, dbname, user, password, in_date, accounts, filename
show_help = False
try:
opts, args = getopt.getopt(sys.argv[1:],'s:d:u:p:t:a:f:h',['server=','database=','user=','password=','date=','accounts=','filename=','help'])
except getopt.GetoptError:
show_help = True
if not opts:
show_help = True
for o, m in opts:
if o in ("-h", "--help"):
usage()
sys.exit()
else:
if o in ("-s", "--server"):
server = m
elif o in ("-d", "--database"):
dbname = m
elif o in ("-u", "--user"):
user = m
elif o in ("-p", "--password"):
password = m
elif o in ("-t", "--date"): #YYYYMMDD
in_date = datetime.datetime.strptime(m,"%Y%m%d").date()
elif o in ("-a", "--account"):
m = m.strip(',')
accounts = m.split(',')
elif o in ("-f", "--filename"):
filename = m
if show_help:
usage()
sys.exit()
def match_contract(rstr,contract_code):
reg = re.compile(rstr)
regMatch = reg.match(contract_code)
return regMatch
# Contract ID:Exchange、Product Code、Currency、Prompt Date、Strike ... Close Price
def getContract(engine):
logging.info("======== loadContracts ========")
df = pd.read_sql(('SELECT [Contract Code],[Exchange],[Product Code],[Currency],[Closing Price],[Contract Type] FROM vw_Contract_Master '), engine) # , chunksize = 10000
now = str(datetime.datetime.now().strftime("%Y"))[0:2]
c_dict = {}
for row in df.itertuples(index=True, name='ContractInfo'):
contract_code = row[1].strip().encode('ascii')
exchange = row[2].strip().encode('ascii')
product_code = row[3].strip().encode('ascii')
currency = row[4].encode('ascii')
close_price = round(row[5],4)
symbol_len = len(product_code)
contract_type = row[6].strip()
option_str = "^(?P<symbol>\w{{{len}}})(?P<strike>[0-9.]+)(?P<callput>[C|P])(?P<expiry>\d{{4}})".format(len = symbol_len)
future_str = "^(?P<symbol>\w{{{len}}})(?P<expiry>\d{{4}})".format(len = symbol_len)
try:
if contract_type == "Option":
cm = match_contract(option_str,contract_code)
prompt_date = now + cm.group("expiry").encode('ascii')
if cm.group("callput") == "P":
c_dict[contract_code]=[exchange,product_code,currency,prompt_date,((cm.group("strike")+"PUT")).encode('ascii'),close_price]
elif cm.group("callput") == "C":
c_dict[contract_code]=[exchange,product_code,currency,prompt_date,((cm.group("strike")+"CALL")).encode('ascii'),close_price]
else:
c_dict[contract_code]=[exchange,product_code,currency,prompt_date,(cm.group("strike")+cm.group("callput")).encode('ascii'),close_price]
logging.info("Not put or call option: {}".format(row))
else:
cm = match_contract(future_str,contract_code)
prompt_date = now + cm.group("expiry").encode('ascii')
c_dict[contract_code]=[exchange,product_code,currency,prompt_date,"",close_price]
except AttributeError:
c_dict[contract_code]=[exchange,product_code,currency,"","",close_price]
logging.warning("ContractID is nonstandard: {} ,save as {}".format(row,c_dict[contract_code]))
return c_dict
# Contract ID: Lots(buy)、Lots(sell)、AVGPrice(buy)、AVGPrice(sell)
def loadTrades(engine,account,date):
logging.info("======== loadTrades: {}".format(date))
df = pd.read_sql(('SELECT [Contract Code],SUM([Quantity]),SUM([Contract Price]*[Quantity])/SUM([Quantity]),[B/S] FROM vw_Trade_Movement WHERE [Client Code] = \'{}\' AND CONVERT(varchar(100),[Trade Date],23) = \'{}\' GROUP BY [Contract Code],[B/S]').format(account,date), engine)
count_row = len(df.index)
if count_row == 0:
logging.warning("There is no records in vw_Trade_Movement for: {} {}".format(date,account))
else:
logging.info("There is are {} records in vw_Trade_Movement for: {} {}".format(count_row,date,account))
t_dict = {}
for row in df.itertuples(index=True, name='TradeInfo'):
contract_code = row[1].strip().encode('ascii')
lots = row[2]
avg_price = row[3]
direction = row[4].strip().encode('ascii')
if contract_code in t_dict.keys():
logging.debug("Both sell and buy trading:{} {}".format(row,t_dict[contract_code]))
else:
t_dict[contract_code] = [0,0,0,0]
if direction == "B" :
t_dict[contract_code][0] = lots
t_dict[contract_code][2] = avg_price
elif direction == "S" :
t_dict[contract_code][1] = lots
t_dict[contract_code][3] = avg_price
else:
t_dict[contract_code] = [0,0,0,0]
logging.warning("Not sell or buy trading: {}, set to 0".format(row))
return t_dict
def loadOpenPosition(engine,account):
logging.info("======== loadOpenPosition ========")
df = pd.read_sql(('SELECT [Contract Code], SUM([Quantity(Long)])-SUM([Quantity(Short)]) FROM vw_Open_Day_Position WHERE [Client Code] = \'{}\' GROUP BY [Contract Code] ').format(account), engine)
count_row = len(df.index)
if count_row == 0:
logging.warning("There is no records in vw_Open_Day_Position for: {} ".format(account))
else:
logging.info("There is are {} records in vw_Open_Day_Position for: {} ".format(count_row,account))
o_dict = {}
for row in df.itertuples(index=True, name='OpenInfo'):
contract_code = row[1].strip().encode('ascii')
open_qty = row[2]
o_dict[contract_code] = open_qty
return o_dict
def loadClosePosition(engine,account):
logging.info("======== loadClosePosition ========")
df = pd.read_sql_query(('SELECT [Contract Code], SUM([Quantity(Long)])-SUM([Quantity(Short)]) FROM vw_Day_Closed_Position WHERE [Client Code] = \'{}\' GROUP BY [Contract Code] ').format(account), engine)
count_row = len(df.index)
if count_row == 0:
logging.warning("There is no records in vw_Day_Closed_Position for: {} ".format(account))
else:
logging.info("There is are {} records in vw_Open_Closed_Position for: {} ".format(count_row,account))
c_dict = {}
for row in df.itertuples(index=True, name='CloseInfo'):
contract_code = row[1].strip().encode('ascii')
close_qty = row[2]
c_dict[contract_code] = close_qty
return c_dict
if __name__ == "__main__":
# default test environment
server = '192.168.15.74'
user = 'TPass'
password = 'TPass1234'
dbname = '20181213'
# default parameter
in_date = (datetime.datetime.now()+datetime.timedelta(days=-1)).strftime("%Y-%m-%d")
accounts = ["F190402","F190436"]
now = datetime.datetime.now().strftime("%Y%m%d_%H%M")
filename = 'report_' + str(now) + '.xlsx'
# parameter from cmd
getOption()
logging.info("The query date is: {}".format(in_date))
logging.info("The query accounts is: {}".format(accounts))
logging.info("The result file will be: {}".format(filename))
# filename exist or not
if os.path.exists(filename):
print "The filename had been used, please choose another name "
sys.exit()
# database connection example (SERVER=192.168.15.74;DATABASE=20181213;UID=TPass;PASSWORD=TPass1234)
params = urllib.quote_plus(("DRIVER={{SQL Server}};SERVER={server};DATABASE={dbname};UID={user};PWD={password}").format(server = server, dbname = dbname, user = user, password = password))
connect_string = ("mssql+pyodbc:///?odbc_connect={}").format(params)
logging.info("The query DB is: {}".format(params))
engine = create_engine(connect_string, echo=True)
# caculate data
list_head = ["交易所","商品代碼","幣別","合約月份","選擇權序列","當日BUY成交口數","當日SELL成交口數","當日BUY平均成交金額","當日SELL平均成交金額","當日結算價LONG","當日結算價SHORT","當日留倉口數","Client Code"]
s = getContract(engine)
list_body = []
for account in accounts:
logging.info("======== product report for: {}".format(account))
t = loadTrades(engine,account,in_date)
o = loadOpenPosition(engine,account)
c = loadClosePosition(engine,account)
for key,value in t.items():
try:
refer = s[key]
except KeyError:
refer = [key,"","","","",0]
logging.debug("There is no matched referance data for: {}, set to {} ".format(key,refer))
try:
open_p = o[key]
except KeyError:
open_p = 0
logging.debug("There is no matched open position for: {}, set to 0 ".format(key))
try:
close_p = c[key]
except KeyError:
close_p = 0
logging.debug("There is no matched close position for: {}, set to 0 ".format(key))
position = open_p + (t[key][0]+t[key][1]) - (2*close_p)
if position >= 0:
tmp = [refer[0],refer[1],refer[2],refer[3],refer[4],t[key][0],t[key][1],t[key][2],t[key][3],refer[5],0,abs(position),account]
list_body.append(tmp)
else:
tmp = [refer[0],refer[1],refer[2],refer[3],refer[4],t[key][0],t[key][1],t[key][2],t[key][3],0,refer[5],abs(position),account]
list_body.append(tmp)
logging.debug("one contract had been finished: {}".format(tmp))
# write into excel
df = pd.DataFrame(list_body, columns=list_head)
df.to_excel(filename, encoding='utf-8', index=False, header=True)
logging.info("The report had been finished: {}".format(filename))
Copy the code