Example #1
0
    def placeImagesAndSumStyles(self, imageLocation, ws, tf):
        '''
        A helper method for export to excel. Place images and the tradesummary stylesin the
        openpyxl ws object
        '''

        # tradeSummaries = list()
        CELLS = 20  # trial and error here
        srf = SumReqFields()

        for loc in imageLocation:
            # Place the format shapes/styles in the worksheet
            tf.formatTrade(ws, srf, anchor=(1, loc[0][0][1]))
            for iloc, fn in zip(loc[0], loc[1]):
                if not os.path.exists(fn):
                    continue
                img = PILImage.open(fn)
                xl = XLImage()
                newSize = xl.adjustSizeByHeight(img.size, CELLS)
                img = img.resize(newSize, PILImage.ANTIALIAS)
                img.save(fn, 'png')
                img = Image(fn)
                if img:
                    cellname = tcell(iloc)
                    ws.add_image(img, cellname)
Example #2
0
    def __init__(self, db=None, source=None):
        '''Initialize and set the db location'''
        settings = QSettings('zero_substance', 'structjour')
        # jdir = settings.value('journal')
        self.settings = settings
        self.db = None
        if not db:
            db = self.settings.value('tradeDb')
        else:
            db = db
        if db:
            self.db = db
        if not self.db:
            title = 'Warning'
            msg = (
                '<h3>Database files have not been set</h3>'
                '<p>Please set a valid location when calling setDB or you may select or '
                'create a new location by selecting file->filesettings</p>')
            msgbx = QMessageBox(QMessageBox.Warning, title, msg,
                                QMessageBox.Ok)
            msgbx.setWindowIcon(QIcon("structjour/images/ZSLogo.png"))
            msgbx.exec()
            return

        self.rc = FinReqCol()
        self.sf = SumReqFields()
        self.createTable()
        ModelBase.session.close()
    def setUpClass(cls):
        '''
        Open up a bunch of statments and add them to a test database for testing stuff
        TODO: Develop the randomtradgenerator write trades to the db for more generic testing
        '''
        settings = QSettings('zero_substance', 'structjour')
        for i, name in enumerate(cls.infiles):
            name = os.path.join(cls.datadir, name)
            x, cls.inputType = getStatementType(name)
            print(cls.inputType)
            if cls.inputType == 'DAS':
                ds = DasStatement(name, settings, cls.thedates[i])
                ds.getTrades(testFileLoc=cls.datadir, testdb=cls.testdb)
            elif cls.inputType == "IB_CSV":
                ibs = IbStatement(db=cls.testdb)
                ibs.openIBStatement(name)
            else:
                continue
            #     self.assertTrue(4 == 5, "Unsupported file type in test_TheTradeObject")

            statement = StatementDB(db=cls.testdb)
            df = statement.getStatement(cls.thedates[i])
            # self.assertFalse(df.empty, f"Found no trades in db on {daDate}")
            dtrade = DefineTrades(cls.inputType)
            dframe, ldf = dtrade.processDBTrades(df)
            tto = TheTradeObject(ldf[0], False, SumReqFields())
            cls.ttos.append(tto)
Example #4
0
 def __init__(self, topMargin, inputlen, spacing=3):
     '''
     Constructor
     :params topMargin: The space at the top before the trade table. Includes the
                        inspire quote and space notes.
     :params inputlen: Don't enter a value here. Its the length of the dframe after processing.
     :params spacing: The space between trade summaries.
     :params frq: The FinReqCol object
     '''
     srf = SumReqFields()
     sumSize = srf.maxrow() + 5
     self.summarySize = sumSize
     self.topMargin = topMargin
     self.inputlen = inputlen
     self.spacing = spacing
     self.DSFAnchor = None
Example #5
0
def loadTradeSummaries(loc, trades):
    '''
    Load up each trade summary in the excel doc into a 1 row DataFrame, return a list
    of these DataFrames. The addresses are supplied by srf plus the loc object that has the
    anchors.
    :params:loc: A list of the rows within the excel doc on which to find the trade summaries
    :return: A list of 1-row DataFrames Each trade is on one row from each of the trade summay forms
    '''

    ldf = list()
    ts = dict()
    srf = SumReqFields()
    reqCol = srf.rc
    newdf = pd.DataFrame(columns=reqCol.values())
    colFormat = srf.tfcolumns

    for i, rowNum in enumerate(loc):
        newdf = DataFrameUtil.createDf(newdf, 1)
        for key in reqCol.keys():
            if key in ['date', 'clean', 'id']:
                continue
            cell = colFormat[reqCol[key]][0]
            if isinstance(cell, list):
                cell = cell[0]
            cell = tcell(cell, anchor=(1, rowNum))
            newdf.iloc[-1][reqCol[key]] = trades[cell].value

        tradekey = str(i + 1) + ' ' + newdf.iloc[0].Name
        ts[tradekey] = newdf
        ldf.append(newdf)
    return ldf, ts
Example #6
0
def whereDateTime(before=None, after=None):
    sf = SumReqFields()
    s = ''
    if before is not None:
        d = pd.Timestamp(before)
        dbef = d.strftime('%Y%m%d')
        tbef = d.strftime('%H:%M:%S')
        s = f'{sf.date} >= "{dbef}" AND {sf.start} >= "{tbef}"'
        if after is not None:
            s += ' AND '
    if after is not None:
        d = pd.Timestamp(after)
        daft = d.strftime('%Y%m%d')
        taft = d.strftime('%H:%M:%S')
        s += f'{sf.date} <= "{daft}" and {sf.start} <= "{taft}"'
    return s
Example #7
0
    def test_formatTrade(self):
        '''
        Test the method TradeFormat.formatTrade. Specifically test that each of the elements in
        srf.tfcolumns has a corresponding elementcorrectly styled in the re-opened workbook and
        that each merged element in srf.tfcolumns is found in the the worsheet.
        '''
        wb = Workbook()
        ws = wb.active

        t = TradeFormat(wb)
        srf = SumReqFields()
        ws = wb.active

        t.formatTrade(ws, srf)

        dispath = "out/SCHNOrK.xlsx"
        if os.path.exists(dispath):
            os.remove(dispath)
        wb.save(dispath)

        wb2 = load_workbook(dispath)
        ws2 = wb2.active

        # test that each listed item in srf.tfcolumns has a corresponding style set in the
        # appropriate cell of the re-opened workbook
        for x in srf.tfcolumns:
            address = srf.tfcolumns[x][0]
            st = srf.tfcolumns[x][1]
            if isinstance(address, list):
                self.assertEqual(ws2[c(address[0])].style, st)
            else:
                self.assertEqual(ws2[c(address)].style, st)

        # test that each list element has a corresponding merged cell group in the worbook
        listofmerge = [
            c(srf.tfcolumns[x][0][0], srf.tfcolumns[x][0][1])
            for x in srf.tfcolumns if isinstance(srf.tfcolumns[x][0], list)
        ]
        wsmerged = ws.merged_cells.ranges
        self.assertEqual(len(listofmerge), len(wsmerged))
        for msmerge in wsmerged:
            self.assertTrue(str(msmerge) in listofmerge)
Example #8
0
def whereDay(after=None, before=None):
    '''
    Return a WHERE clause for dates of a trade.  If both parameters are None, return an empty string
    :params after: Timestamp or str. The earliest day of a trade.
    :params before: Timestamp or str. The latest day of a trade.
    :return: A where clause for earliest and/or latest day of a trade.
    '''
    sf = SumReqFields()
    s = ''
    if before is not None:
        d = pd.Timestamp(before)
        dbef = d.strftime('%Y%m%d')
        s = f'{sf.date} <= {dbef}'
        if after is not None:
            s += ' AND '
    if after is not None:
        d = pd.Timestamp(after)
        daft = d.strftime('%Y%m%d')
        s += f'{sf.date} >= {daft}'
    return s
Example #9
0
def whereTimeOfDay(bstart=None, estart=None):
    '''
    Return a WHERE clause for the start time of a trade.  If both parameters are None, return an empty string
    :params bstart: Timestamp or str. The earliest time of day to start
    :params estart: Timestamp or str. The latest time of day to start
    :return: A where clause for beginning and/or end start time
    '''
    sf = SumReqFields()
    s = ''
    if bstart is not None:
        d = pd.Timestamp(bstart)
        dstart = d.strftime("%H:%S:%M")
        s = f'{sf.start} >= {dstart}'
        if estart is not None:
            s += ' AND'
    if estart is not None:
        d = pd.Timestamp(estart)
        dstart = d.strftime("%H:%S:%M")
        s = f'{sf.start} <= {dstart}'

    return s
Example #10
0
    def test_populateXLDailyFormulas(self):
        '''
        Test populateXLDailyFormulas. Specifically test that the value written to the
        ws is a formula (it begins with =).
        '''
        srf = SumReqFields()
        self.t.populateXLDailyFormulas
        self.t.populateXLDailyFormulas(self.imageLocation, self.wb.active)
        # self.t.saveXL(self.wb, self.jf)
        ws = self.wb.active

        # Get the anchor from imageLocation, Get the form coord from tfcolumns using a key
        # common to tfcolumns and tfformulas
        for loc in self.imageLocation:
            anchor = (1, loc[0][0][1])
            for key in srf.tfformulas:
                cell = srf.tfcolumns[key][0]
                if isinstance(cell, list):
                    cell = cell[0]
                valcell = tcell(cell, anchor=anchor)
                # print(ws[valcell].value)
                self.assertEqual(ws[valcell].value.find('='), 0)
Example #11
0
    def populateXLDailyFormulas(self, imageLocation, ws):
        '''
        Helper method for export to excel. Populate the excel formulas in the daily summary forms.
        The formulas are in self.ts and the information to transalte cell location is in
        imageLocation
        '''
        srf = SumReqFields()
        for loc, tradekey in zip(imageLocation, self.ts):
            tto = self.ts[tradekey]

            # populate the trade information
            for key in srf.tfcolumns:
                cell = srf.tfcolumns[key][0]
                if isinstance(cell, list):
                    cell = cell[0]
                tradeval = tto[key].unique()[0]

                # Put some formulas in each trade Summary
                if key in srf.tfformulas:

                    anchor = (1, loc[0][0][1])
                    formula = srf.tfformulas[key][0]
                    args = []
                    for c in srf.tfformulas[key][1:]:
                        args.append(tcell(c, anchor=anchor))
                    tradeval = formula.format(*args)

                if not tradeval:
                    continue
                if isinstance(tradeval,
                              (pd.Timestamp, dt.datetime, np.datetime64)):
                    tradeval = pd.Timestamp(tradeval)
                elif isinstance(tradeval, bytes):
                    tradeval = None

                ws[tcell(cell, anchor=(1, loc[0][0][1]))] = tradeval

        return
from PyQt5.QtCore import QSettings

from structjour.definetrades import DefineTrades
from structjour.thetradeobject import TheTradeObject, SumReqFields
from structjour.colz.finreqcol import FinReqCol

from structjour.statements.ibstatementdb import StatementDB
from structjour.statements.ibstatement import IbStatement
from structjour.statements.statement import getStatementType
from structjour.statements.dasstatement import DasStatement
from structjour.stock.utilities import isNumeric

# pylint: disable = C0103, W0212, C0111

# Global
grf = SumReqFields()


class TestTheTradeObject(unittest.TestCase):
    '''
    Test the functions and methods in thetradeobject module. TheTradeObject input requires a bunch of
    prerequisites.
    1. Trade transactions need to be read into the database from DAS or the Broker statement
    2. A statment needs to be created which is a collection of trades from the db from a single day
    3. The transactions in the statment need to be processed into trades (a collection of transactions
        organized by trade with associated data starttime, average price, balance and user info)
    The transition from transactions to trades is achieved by DefineTrades and TheTradeObject.
    DefineTrades is responsible for:
        separating which transactions go together, numbering the trades (for each day), giving
        a common start time for each tx in a trade, calculating PL, calculating PL summary, balance and
        naming the trade. (Note that sometimes information is incomplete)
Example #13
0
def registerTrades(wb, theDate):

    ibdb = StatementDB()
    df = ibdb.getStatement(theDate)
    x = ibdb.getNumTicketsForDay(theDate)
    if not x[0] or not x[1]:
        msg = f'''found {x[0]} tickets and {x[1]} trades. Nothing to process for the date {theDate.strftime('%A %d, %Y')}in the DB'''
        return msg
    tu = DefineTrades('DB')
    df, ldf = tu.processDBTrades(df)

    ts, entries = ibdb.getTradeSummaries(theDate)
    # self.ts = setTradeSummaryHeaders(ts)

    drc = DisReqCol(theDate)

    tlog = wb["Trade Log"]
    account = tlog['I1'].value

    startSearch = False
    ix = -2
    cols = drc.tfcolumns
    # Here is a list of the keys to use cols.keys() of the trade log DataFrame
    # ['date', 'time', 'side', 'symb', 'entry1', 'acctbal', 'shares',
    # 'stoploss', 'targ', 'avgexit', 'pl', 'notes'])
    # Not bothering with the abstraction (drc.name) because this is entirely ours.

    srf = SumReqFields()

    ids = list()

    for row in tlog.iter_rows():
        # Unconventional loop stuff
        anchor = (1, row[0].row)
        keys = list(ts.keys())
        if startSearch is True:
            idcol = cols['id'][0][0] - 1
            if row[idcol].value:
                ids.append(row[idcol].value)
            if not row[0].value:
                startSearch = False
                ix = 0

        if row[0].value == 'Date':
            startSearch = True

        if ix >= 0 and ix < len(keys):

            while True and ix < len(keys):
                key = keys[ix]
                tdf = ts[key]
                if not gotAnyExits(tdf) or tdf['id'].unique()[0] in ids or (
                        tdf['Account'].unique()[0] != account):
                    if tdf['Account'].unique()[0] not in ['SIM', 'Live']:
                        raise ValueError('Programmer exception in search of weird data')
                    # Continue the inner loop -- keep row from the outer loop loop
                    ix += 1
                    continue

                # date
                cell = tcell(cols['date'][0], anchor=anchor)
                tlog[cell] = theDate

                # time
                cell = tcell(cols['time'][0], anchor=anchor)
                tim = tdf[srf.start].unique()[0]
                tlog[cell] = tim

                # side
                name = tdf[srf.name].unique()[0]
                if name:
                    cell = tcell(cols['side'][0], anchor=anchor)
                    tlog[cell] = name.split()[1]

                # symb
                cell = tcell(cols['symb'][0], anchor=anchor)
                tlog[cell] = name.split()[0]

                # entry1
                cell = tcell(cols['entry1'][0], anchor=anchor)
                tlog[cell] = tdf[srf.entry1].unique()[0]

                # Account Balance (setting an excel formula)
                cell = tcell(cols['acctbal'][0], anchor=anchor)
                formula = "=$M$3+SUM($N$7:$N{})".format(row[0].row - 1)
                tlog[cell] = formula

                # "shares"
                cell = tcell(cols['shares'][0], anchor=anchor)
                shares = tdf[srf.shares].unique()[0].split()[0]
                if len(shares) > 0:
                    try:
                        ishares = int(shares)
                    except ValueError:
                        ishares = 0
                tlog[cell] = ishares

                # stoploss
                cell = tcell(cols['stoploss'][0], anchor=anchor)
                sl = tdf[srf.stoploss].unique()[0]
                if isinstance(sl, bytes):
                    sl = None
                tlog[cell] = sl

                # target
                cell = tcell(cols['targ'][0], anchor=anchor)
                target = tdf[srf.targ].unique()[0]
                if isinstance(target, bytes):
                    target = None
                tlog[cell] = target

                # avgExit
                cell = tcell(cols['avgexit'][0], anchor=anchor)
                tlog[cell] = getAvgExit(tdf)

                # P/L
                cell = tcell(cols['pl'][0], anchor=anchor)
                pl = tdf[srf.pl].unique()[0]

                # Don't know how these are sneaking through-- Is it only on legacy files?
                if isinstance(pl, bytes):
                    pl = 0.0
                tlog[cell] = pl

                # Strategy
                cell = tcell(cols['strat'][0], anchor=anchor)
                strat = tdf[srf.strat].unique()[0]
                tlog[cell] = strat

                # notes (from the mistake note field)
                cell = tcell(cols['notes'][0], anchor=anchor)
                note = tdf[srf.mstknote].unique()[0]
                tlog[cell] = note

                # id (from the database)
                cell = tcell(cols['id'][0], anchor=anchor)
                id = tdf['id'].unique()[0]
                tlog[cell] = id

                # break the inner loop
                break

            ix += 1
            if ix >= len(keys):
                # done with outer loop
                break
    return None
Example #14
0
def registerTradesOLD(tsList, wb):
    for fname, theDate in tsList:
        wb2 = load_workbook(fname)
        trades = wb2["Sheet"]

        tradeLocation = getTradeSummaryFormLocations(trades)

        ldf, ts = loadTradeSummaries(tradeLocation, trades)

        drc = DisReqCol(theDate)

        tlog = wb["Trade Log"]

        startSearch = False
        ix = -2
        cols = drc.tfcolumns
        # Here is a list of the keys to use cols.keys() of the trade log DataFrame
        # ['date', 'time', 'side', 'symb', 'entry1', 'acctbal', 'shares',
        # 'stoploss', 'targ', 'avgexit', 'pl', 'notes'])
        # Not bothering with the abstraction (drc.name) because this is entirely ours.

        srf = SumReqFields()

        for row in tlog.iter_rows():
            anchor = (1, row[0].row)

            if startSearch is True:
                if not row[0].value:
                    startSearch = False
                    ix = 0
            if row[0].value == 'Date':
                startSearch = True

            if ix >= 0:
                tdf = ldf[ix]
                if not gotAnyExits(tdf):
                    continue

                # date
                cell = tcell(cols['date'][0], anchor=anchor)
                tlog[cell] = theDate

                # time
                cell = tcell(cols['time'][0], anchor=anchor)
                tim = tdf[srf.start].unique()[0]
                tlog[cell] = tim

                # side
                name = tdf[srf.name].unique()[0]
                if name:
                    cell = tcell(cols['side'][0], anchor=anchor)
                    tlog[cell] = name.split()[1]

                # symb
                cell = tcell(cols['symb'][0], anchor=anchor)
                tlog[cell] = name.split()[0]

                # entry1
                cell = tcell(cols['entry1'][0], anchor=anchor)
                tlog[cell] = tdf[srf.entry1].unique()[0]

                # Account Balance (setting an excel formula)
                cell = tcell(cols['acctbal'][0], anchor=anchor)
                formula = "=$M$3+SUM($N$7:$N{})".format(row[0].row - 1)
                tlog[cell] = formula

                # "shares"
                cell = tcell(cols['shares'][0], anchor=anchor)
                shares = tdf[srf.shares].unique()[0].split()[0]
                if len(shares) > 0:
                    try:
                        ishares = int(shares)
                    except ValueError:
                        ishares = 0
                tlog[cell] = ishares

                # stoploss
                cell = tcell(cols['stoploss'][0], anchor=anchor)
                sl = tdf[srf.stoploss].unique()[0]
                tlog[cell] = sl

                # target
                cell = tcell(cols['targ'][0], anchor=anchor)
                target = tdf[srf.targ].unique()[0]
                tlog[cell] = target

                # avgExit
                cell = tcell(cols['avgexit'][0], anchor=anchor)
                tlog[cell] = getAvgExit(tdf)

                # P/L
                cell = tcell(cols['pl'][0], anchor=anchor)
                pl = tdf[srf.pl].unique()[0]
                tlog[cell] = pl

                # Strategy
                cell = tcell(cols['strat'][0], anchor=anchor)
                strat = tdf[srf.strat].unique()[0]
                tlog[cell] = strat

                # notes (from the mistake note field)
                cell = tcell(cols['notes'][0], anchor=anchor)
                note = tdf[srf.mstknote].unique()[0]
                tlog[cell] = note

                ix = ix + 1
                if ix == len(ldf):
                    break
Example #15
0
    def layoutExcelData(self, df, ldf, imageNames):
        '''
        1) Determine the locations in the Excel doc to place trade summaries, trade tables and
            images.
        2) Create the empty rows and place the trade tables in the df according to the locations.
        :params df: We requre the df as  a whole because we are adding rows to it.
        :params ldf: A list of dataframes, each a trade, each one is placed into our new skeletal
                     layout for excel
        :return (Imagelocation, df): ImageLocation contains
                                [ [list of image location],   # up to 3 per trade
                                  [list of image names],      # up to 3 per trade
                                  Start time,
                                  trade dur,
                                ]
        '''

        imageLocation = list()
        srf = SumReqFields()
        sumSize = srf.maxrow() + 5
        summarySize = sumSize
        spacing = 3

        # Image column location
        c1col = 13
        c2col = 1
        c3col = 9
        frq = FinReqCol()
        newdf = DataFrameUtil.createDf(df, self.topMargin)

        df = newdf.append(df, ignore_index=True)
        deleteme = []
        for i, tdf in enumerate(ldf):
            theKey = tdf[frq.tix].unique()[-1]
            if len(theKey) == 0:
                deleteme.append(i)
                continue
            imageName = imageNames[theKey]
            xtraimage = 0  # Add space for second/third image
            if len(imageName) > 1:
                xtraimage = 21
            ilocs = []
            # Need 1 entry even if there are no images
            ilocs.append((c1col, len(tdf) + len(df) + spacing))
            for i in range(0, len(imageName)):
                if i == 1:
                    ilocs.append((c2col, len(tdf) + len(df) + spacing + 20))
                elif i == 2:
                    ilocs.append((c3col, len(tdf) + len(df) + spacing + 20))

            # Holds image locations, image name, trade start time, trade duration as delta
            imageLocation.append([
                ilocs, imageName,
                tdf.Start.unique()[-1],
                tdf.Duration.unique()[-1]
            ])

            # Append the mini trade table then add rows to fit the tradeSummary form
            df = df.append(tdf, ignore_index=True)
            df = DataFrameUtil.addRows(df, summarySize + xtraimage)
        for d in deleteme:
            ldf.pop(d)
        return imageLocation, df
Example #16
0
    def __init__(self, sc, jf, df):
        '''
        Initialize the obect and create a Widget dictionary using the same keys as the keys to the
        tto object to populate the data.
        '''
        self.jf = jf
        self.df = df
        if self.df is not None:
            self.pickleitnow()
        self.ts = dict()
        self.entries = dict()
        rc = SumReqFields()
        self.timeFormat = '%H:%M:%S'

        self.sc = sc
        self.tradeSummaries = None

        # Widget Dictionary. Keys are same keys for TheTradeObject.TheTrade object
        wd = dict()
        wd[rc.name] = sc.ui.title
        wd[rc.acct] = sc.ui.account
        wd[rc.strat] = sc.ui.strategy
        # wd[rc.link1] = sc.ui.link
        wd[rc.pl] = sc.ui.pl
        wd[rc.start] = sc.ui.start
        wd[rc.dur] = sc.ui.dur
        wd[rc.shares] = sc.ui.pos
        wd[rc.mktval] = sc.ui.mkt
        wd[rc.targ] = sc.ui.targ
        wd[rc.targdiff] = sc.ui.targDiff
        wd[rc.stoploss] = sc.ui.stop
        wd[rc.sldiff] = sc.ui.stopDiff
        wd[rc.rr] = sc.ui.rr
        wd[rc.realrr] = sc.ui.realRR
        wd[rc.maxloss] = sc.ui.maxLoss
        wd[rc.mstkval] = sc.ui.lost
        wd[rc.mstknote] = sc.ui.sumNote
        wd[rc.entry1] = sc.ui.entry1
        wd[rc.entry2] = sc.ui.entry2
        wd[rc.entry3] = sc.ui.entry3
        wd[rc.entry4] = sc.ui.entry4
        wd[rc.entry5] = sc.ui.entry5
        wd[rc.entry6] = sc.ui.entry6
        wd[rc.entry7] = sc.ui.entry7
        wd[rc.entry8] = sc.ui.entry8
        wd[rc.exit1] = sc.ui.exit1
        wd[rc.exit2] = sc.ui.exit2
        wd[rc.exit3] = sc.ui.exit3
        wd[rc.exit4] = sc.ui.exit4
        wd[rc.exit5] = sc.ui.exit5
        wd[rc.exit6] = sc.ui.exit6
        wd[rc.exit7] = sc.ui.exit7
        wd[rc.exit8] = sc.ui.exit8
        wd[rc.time1] = sc.ui.time1
        wd[rc.time2] = sc.ui.time2
        wd[rc.time3] = sc.ui.time3
        wd[rc.time4] = sc.ui.time4
        wd[rc.time5] = sc.ui.time5
        wd[rc.time6] = sc.ui.time6
        wd[rc.time7] = sc.ui.time7
        wd[rc.time8] = sc.ui.time8
        wd[rc.eshare1] = sc.ui.share1
        wd[rc.eshare2] = sc.ui.share2
        wd[rc.eshare3] = sc.ui.share3
        wd[rc.eshare4] = sc.ui.share4
        wd[rc.eshare5] = sc.ui.share5
        wd[rc.eshare6] = sc.ui.share6
        wd[rc.eshare7] = sc.ui.share7
        wd[rc.eshare8] = sc.ui.share8
        wd[rc.diff1] = sc.ui.diff1
        wd[rc.diff2] = sc.ui.diff2
        wd[rc.diff3] = sc.ui.diff3
        wd[rc.diff4] = sc.ui.diff4
        wd[rc.diff5] = sc.ui.diff5
        wd[rc.diff6] = sc.ui.diff6
        wd[rc.diff7] = sc.ui.diff7
        wd[rc.diff8] = sc.ui.diff8
        wd[rc.pl1] = sc.ui.pl1
        wd[rc.pl2] = sc.ui.pl2
        wd[rc.pl3] = sc.ui.pl3
        wd[rc.pl4] = sc.ui.pl4
        wd[rc.pl5] = sc.ui.pl5
        wd[rc.pl6] = sc.ui.pl6
        wd[rc.pl7] = sc.ui.pl7
        wd[rc.pl8] = sc.ui.pl8
        wd[rc.explain] = sc.ui.explain
        wd[rc.notes] = sc.ui.notes

        self.rc = rc
        self.wd = wd
        self.imageNames = None
        self.sc.loadLayoutForms(self)
Example #17
0
    def populateDailySummaryForm(self, TheTradeList, mistake, ws, anchor):
        '''
        Populate the daily Summary Form. The PL values are retrieved from TheTradeList. The static
        labels are set earlier. This method sets some statistics and notes for things like
        regarding average winners/losers etc.
        :params listOfTrade: A python list of the Summary Trade DataFrame, aka TheTrade, each one
                             is a single row DataFrame containg all the data for trade summaries.
        :params mistke:
        :params ws: The openpyxl Worksheet object
        :raise Value Error: When pl is misformatted and cannot be used.
        '''
        srf = SumReqFields()
        liveWins = list()
        liveLosses = list()
        simWins = list()
        simLosses = list()
        maxTrade = (0, "notrade")
        minTrade = (0, "notrade")
        # Didnot save the Trade number in TheTrade.  These should be the same order...
        count = 0

        for TheTrade in TheTradeList:
            pl = TheTrade[srf.pl].unique()[0]
            live = True if TheTrade[srf.acct].unique()[0] == "Live" else False
            count = count + 1

            # A bug-ish inspired baby-sitter
            if isinstance(pl, str):
                if pl == '':
                    pl = 0
                else:
                    try:
                        pl = float(pl)
                    except NameError:
                        raise ValueError(
                            'Malformed float for variable pl in createDailySummary'
                        )

            if float(pl) > maxTrade[0]:
                maxTrade = (pl, "Trade{0}, {1}, {2}".format(
                    count, TheTrade[srf.acct].unique()[0],
                    TheTrade[srf.name].unique()[0]))
            if pl < minTrade[0]:
                minTrade = (pl, "Trade{0}, {1}, {2}".format(
                    count, TheTrade[srf.acct].unique()[0],
                    TheTrade[srf.name].unique()[0]))

            if live:
                if pl > 0:
                    liveWins.append(pl)
                else:
                    liveLosses.append(pl)
            else:
                if pl > 0:
                    simWins.append(pl)
                else:
                    simLosses.append(pl)

        anchor = (anchor[0], anchor[1] + mistake.numTrades + 5)
        self.DSFAnchor = anchor

        dailySumData = dict()
        dailySumData['livetot'] = sum([sum(liveWins), sum(liveLosses)])

        numt = len(liveWins) + len(liveLosses)
        if numt == 0:
            dailySumData['livetotnote'] = "0 Trades"
        else:
            note = "{0} Trade{1}, {2} Winner{3}, {4}, Loser{5}"
            note = note.format(numt, "" if numt == 1 else "s", len(liveWins),
                               "" if len(liveWins) == 1 else "s",
                               len(liveLosses),
                               "" if len(liveLosses) == 1 else "s")
            dailySumData['livetotnote'] = note
        dailySumData['simtot'] = sum([sum(simWins), sum(simLosses)])

        # 9 trades,  3 Winners, 6 Losers
        numt = len(simWins) + len(simLosses)
        if numt == 0:
            dailySumData['simtotnote'] = "0 Trades"
        else:  # 4 trades, 1 Winner, 3 Losers
            note = "{0} Trade{1}, {2} Winner{3}, {4}, Loser{5}"
            note = note.format(numt, "" if numt == 1 else "s",
                               len(simWins), "" if len(simWins) == 1 else "s",
                               len(simLosses),
                               "" if len(simLosses) == 1 else "s")
            dailySumData['simtotnote'] = note

        dailySumData['highest'] = maxTrade[0]
        dailySumData['highestnote'] = maxTrade[1]
        dailySumData['lowest'] = minTrade[0]
        dailySumData['lowestnote'] = minTrade[1]
        if (len(liveWins) + len(simWins)) == 0:
            dailySumData['avgwin'] = 0
        else:
            dailySumData['avgwin'] = sum(
                [sum(liveWins), sum(simWins)]) / (len(liveWins) + len(simWins))
        dailySumData['avgwinnote'] = "X {} =  ${:.2f}".format(
            len(liveWins) + len(simWins), sum([sum(liveWins),
                                               sum(simWins)]))
        if len(liveLosses) + len(simLosses) == 0:
            dailySumData['avgloss'] = 0
        else:
            dailySumData['avgloss'] = sum([
                sum(liveLosses), sum(simLosses)
            ]) / (len(liveLosses) + len(simLosses))
        dailySumData['avglossnote'] = "X {} =  (${:.2f})".format(
            len(liveLosses) + len(simLosses),
            abs(sum([sum(liveLosses), sum(simLosses)])))

        for key in dailySumData.keys():
            rng = mistake.dailySummaryFields[key][0]
            if isinstance(rng, list):
                rng = rng[0]
            ws[tcell(rng, anchor=anchor)] = dailySumData[key]
Example #18
0
    def gatherDSumData(self, ts=None):
        '''
        The dialog does not use this. It shows the info in charts. It is called by the export to excel stuff.  
        Put together into a dictionary the data for populating the Daily Summary
        :ts: TradeSummary dictionary. If called without running runDialog, this must be provided
             If this is called from within the dialog, leave it blank.
        '''
        if ts:
            self.ts = ts
        srf = SumReqFields()
        liveWins = list()
        liveLosses = list()
        simWins = list()
        simLosses = list()
        maxTrade = (0, "notrade")
        minTrade = (0, "notrade")
        # Didnot save the Trade number in TheTrade.  These should be the same order...
        count = 0

        if not self.ts:
            logging.info('Trade data not found')
            return

        # Gather all the data
        for key in self.ts:
            TheTrade = self.ts[key]
            pl = TheTrade[srf.pl].unique()[0]
            live = True if TheTrade[srf.acct].unique()[0] == "Live" else False
            count = count + 1

            if pl is None:
                pl = 0.0
            # A bug-ish inspired baby-sitter
            elif isinstance(pl, str) or isinstance(pl, bytes):
                pl = 0
            if float(pl) > maxTrade[0]:
                maxTrade = (pl, "Trade{0}, {1}, {2}".format(
                    count, TheTrade[srf.acct].unique()[0], TheTrade[srf.name].unique()[0]))
            if pl < minTrade[0]:
                minTrade = (pl, "Trade{0}, {1}, {2}".format(
                    count, TheTrade[srf.acct].unique()[0], TheTrade[srf.name].unique()[0]))

            if live:
                if pl > 0:
                    liveWins.append(pl)
                else:
                    liveLosses.append(pl)
            else:
                if pl > 0:
                    simWins.append(pl)
                else:
                    simLosses.append(pl)

        dailySumData = OrderedDict()

        # row1
        dailySumData['livetot'] = fc(sum([sum(liveWins), sum(liveLosses)]))

        numt = len(liveWins) + len(liveLosses)
        if numt == 0:
            dailySumData['livetotnote'] = "0 Trades"
        else:
            note = "{0} Trade{1}, {2} Winner{3}, {4}, Loser{5}"
            note = note.format(numt, "" if numt == 1 else "s", len(liveWins),
                               "" if len(liveWins) == 1 else "s", len(
                                   liveLosses),
                               "" if len(liveLosses) == 1 else "s")
            dailySumData['livetotnote'] = note

        # row2
        dailySumData['simtot'] = fc(sum([sum(simWins), sum(simLosses)]))

        # 9 trades,  3 Winners, 6 Losers
        numt = len(simWins) + len(simLosses)
        if numt == 0:
            dailySumData['simtotnote'] = "0 Trades"
        else:  # 4 trades, 1 Winner, 3 Losers
            note = "{0} Trade{1}, {2} Winner{3}, {4}, Loser{5}"
            note = note.format(numt, "" if numt == 1 else "s",
                               len(simWins), "" if len(simWins) == 1 else "s",
                               len(simLosses), "" if len(simLosses) == 1 else "s")
            dailySumData['simtotnote'] = note

        # row3
        dailySumData['highest'] = fc(maxTrade[0])
        dailySumData['highestnote'] = maxTrade[1]

        # row 4
        dailySumData['lowest'] = fc(minTrade[0])
        dailySumData['lowestnote'] = minTrade[1]

        # row 5
        if (len(liveWins) + len(simWins)) == 0:
            dailySumData['avgwin'] = '$0.00'
        else:
            dailySumData['avgwin'] = fc(sum(
                [sum(liveWins), sum(simWins)]) / (len(liveWins) + len(simWins)))
        dailySumData['avgwinnote'] = "X {} =  {}".format(
            len(liveWins) + len(simWins), fc(sum([sum(liveWins), sum(simWins)])))

        # row 6
        if len(liveLosses) + len(simLosses) == 0:
            dailySumData['avgloss'] = '$0.00'
        else:
            dailySumData['avgloss'] = fc(sum([sum(liveLosses), sum(
                simLosses)]) / (len(liveLosses) + len(simLosses)))
        dailySumData['avglossnote'] = "X {} =  (${:.2f})".format(
            len(liveLosses) + len(simLosses), abs(sum([sum(liveLosses), sum(simLosses)])))
        return dailySumData
Example #19
0
    def __init__(self, numTrades, anchor=(1, 1)):

        self.anchor = anchor
        self.numTrades = numTrades

        # Create the data structure to make a styled shape for the Mistake Summary Form
        # 'key':[rng,style, value]
        mistakeFields = {
            'title': [[(1, 1), (12, 2)], 'titleStyle', 'Mistake Summary'],
            'headname': [[(1, 3), (2, 3)], 'normStyle', 'Name'],
            'headpl': [(3, 3), 'normStyle', "PnL"],
            'headLossPL': [(4, 3), 'normStyle', "Lost P/L"],
            'headmistake': [[(5, 3), (12, 3)], 'normStyle',
                            "Mistake or pertinent feature of trade."],

        }

        # Create the data structure to create a styled shape for the Daily Summary Form
        # 'key':[rng, style, value]
        dailySummaryFields = {
            'title': [[(1, 1), (12, 2)], 'titleStyle', "Daily PnL Summary"],
            'headlivetot': [[(1, 3), (2, 3)], 'normStyle', "Live Total"],
            'headsimtot': [[(1, 4), (2, 4)], 'normStyle', "Sim Total"],
            'headhighest': [[(1, 5), (2, 5)], 'normStyle', "Highest Profit"],
            'headlowest': [[(1, 6), (2, 6)], 'normStyle', "Largest Loss"],
            'headavgwin': [[(1, 7), (2, 7)], 'normStyle', "Average Win"],
            'headavgloss': [[(1, 8), (2, 8)], 'normStyle', "Average Loss"],
            'livetot': [(3, 3), 'normalNumber'],
            'simtot': [(3, 4), 'normalNumber'],
            'highest': [(3, 5), 'normalNumber'],
            'lowest': [(3, 6), 'normalNumber'],
            'avgwin': [(3, 7), 'normalNumber'],
            'avgloss': [(3, 8), 'normalNumber'],
            'livetotnote': [[(4, 3), (12, 3)], 'normStyle'],
            'simtotnote': [[(4, 4), (12, 4)], 'normStyle'],
            'highestnote': [[(4, 5), (12, 5)], 'normStyle'],
            'lowestnote': [[(4, 6), (12, 6)], 'normStyle'],
            'avgwinnote': [[(4, 7), (12, 7)], 'normStyle'],
            'avglossnote': [[(4, 8), (12, 8)], 'normStyle'],
        }

        # Dynamically add rows to mistakeFields
        # for name, trade pl, lost pl, mistake note (n, tpl, pl, m)
        for i in range(numTrades):
            n = "name" + str(i + 1)
            tp = "tpl" + str(i + 1)
            p = "pl" + str(i + 1)
            m = "mistake" + str(i + 1)
            ncells = [(1, 4 + i), (2, 4 + i)]  # [(1,4), (2,4)]
            tpcells = (3, 4 + i)
            pcells = (4, 4 + i)
            mcells = [(5, 4 + i), (12, 4 + i)]
            mistakeFields[n] = [ncells, 'normStyle']
            mistakeFields[tp] = [tpcells, 'normalNumber']
            mistakeFields[p] = [pcells, 'normalNumber']
            mistakeFields[m] = [mcells, 'finalNoteStyle']

        mistakeFields['blank1'] = [
            [(1, 4 + numTrades), (2, 4 + numTrades)], 'normStyle']
        mistakeFields['total2'] = [(3, 4 + numTrades), 'normalNumber']
        mistakeFields['total'] = [(4, 4 + numTrades), 'normalNumber']
        mistakeFields['blank2'] = [
            [(5, 4 + numTrades), (12, 4 + numTrades)], 'normStyle']

        # Excel formulas belong in the mstkval and mstknote columns. The srf.tfcolumns bit
        # are the target addresses for the Excel formula. The cell translation
        # takes place when we create and populate the Workbook.
        formulas = dict()
        srf = SumReqFields()
        for i in range(numTrades):

            tp = "tpl" + str(i + 1)
            formulas[tp] = ['={0}', srf.tfcolumns[srf.pl][0][0]]
            p = "pl" + str(i + 1)
            formulas[p] = ['={0}', srf.tfcolumns[srf.mstkval][0][0]]
            m = "mistake" + str(i + 1)
            formulas[m] = ['={0}', srf.tfcolumns[srf.mstknote][0][0]]

        self.formulas = formulas
        self.mistakeFields = mistakeFields
        self.dailySummaryFields = dailySummaryFields