예제 #1
0
파일: histvol.py 프로젝트: blais/ameritrade
def main():
    """Compute various vol estimates."""
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    parser.add_argument('-s',
                        '--symbol',
                        action='store',
                        default='SPY',
                        help="Symbol to compute on")
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    # Fetch call chain for underlying.
    hist = api.GetPriceHistory(symbol=args.symbol,
                               frequency=1,
                               frequencyType='daily',
                               period=2,
                               periodType='year')
    candle = price_history_to_arrays(hist)

    # Compute historical volatility estimates and centile of vol distribution of
    # underlying over various time periods.
    header = ['windays', 'annual_vol', 'iv_percentile', 'mean', 'std']
    rows = [header]
    for days in [7, 15, 20, 30, 60, 90, 120, 180, 365, None]:
        centiles = True
        if days is None:
            centiles = False
            days = candle.datetime.shape[0]
        vol = historical_volatility(candle.datetime[-days:],
                                    candle.close[-days:])

        if centiles:
            _, vols = historical_volatility_dist(candle.datetime, candle.close,
                                                 days)
            assert len(vols) > 0
            meanvol = numpy.mean(vols)
            stdvol = numpy.std(vols)
            centile = norm.cdf(vol, meanvol, stdvol)
            rows.append([days, vol, centile, meanvol, stdvol])
            # print("Vol over {:3} days: {:8.2f}"
            #       "  (IVpct: {:5.1%}; mean/std: {:.1f}~{:.1f})".format(
            #           days, vol, centile, meanvol, stdvol))
        else:
            #print("Vol over {:3} days: {:8.2f}".format(days, vol))
            rows.append([days, vol, '', '', ''])
    convert = lambda v: Decimal(v).quantize(Q) if v else ''
    table = (petl.wrap(rows).convert('annual_vol', convert).convert(
        'iv_percentile',
        convert).convert('mean',
                         convert).convert('std',
                                          convert).cut('windays', 'mean',
                                                       'std', 'annual_vol',
                                                       'iv_percentile'))
    print(table.lookallstr())
예제 #2
0
def main():
    parser = argparse.ArgumentParser()
    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    # Success!
    print(api)
예제 #3
0
파일: client.py 프로젝트: blais/ameritrade
def main():
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    accountId = utils.GetMainAccount(api)
예제 #4
0
def main():
    parser = argparse.ArgumentParser(description=__doc__.strip())

    parser.add_argument('--betasym',
                        default='SPY',
                        help='Symbol to use as reference for beta')

    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    accountId = utils.GetMainAccount(api)

    # Get the account's portfolio stock positions.
    all_positions = utils.GetPositions(api, accountId)
    positions = [(pos.instrument.symbol, pos.longQuantity - pos.shortQuantity)
                 for pos in all_positions
                 if pos.instrument.assetType == 'EQUITY']
    positions.append(('$SPX.X', Decimal('1')))
    positions.append(('SPY', Decimal('1')))
    positions = [list(x) for x in sorted(positions)]

    # Get betas from the API.
    for row in positions:
        symbol = row[0]
        api_beta = GetBeta(api, symbol)
        row.append(api_beta.quantize(Q))

    # Get time series for the benchmark.
    for periodType in PERIOD_TYPES:
        # Get benchmark returns for that period type.
        time, bench_returns = GetReturns(api, args.betasym, periodType)

        # Get price time series for all symbols.
        for row in positions:
            symbol = row[0]
            ptime, returns = GetReturns(api, symbol, periodType)
            if time.shape != ptime.shape:
                print((time.shape, ptime.shape, row))
                pyplot.plot(time, bench_returns)
                pyplot.plot(ptime, returns)
                pyplot.show()
                computed_beta = Decimal('-100')
            else:
                assert list(time) == list(ptime)
                cov = numpy.cov(returns, bench_returns)
                computed_beta = cov[0, 1] / cov[1, 1]
            row.append(Decimal(computed_beta).quantize(Q))

    header = ['symbol', 'quantity', 'api_beta'] + PERIOD_TYPES
    positions.insert(0, header)
    table = (petl.wrap(positions).cutout('quantity'))
    print(table.lookallstr())
예제 #5
0
def main():
    """Compute various vol estimates."""
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    # Fetch account information.
    #
    # This does appear not suffer time to settlement or delays, so could be used
    # to build monitoring UI.
    accounts = api.GetAccounts(fields='positions')

    dfpos = GetPositions(accounts)
    print(dfpos.to_string())
예제 #6
0
def main():
    """Compute various vol estimates."""
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    parser.add_argument('-s',
                        '--symbol',
                        action='store',
                        default='SPY',
                        help="Symbol to compute on")
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    # Fetch call chain for underlying.
    tz = tzlocal.get_localzone()
    get_ts = lambda *args: int(
        datetime.datetime(*args, tzinfo=tz).timestamp()) * 1000
    # start = get_ts(2021, 8, 20, 9, 30, 0)
    # end = start + 2 * 60 * 60 * 1000
    start = None
    end = get_ts(2021, 4, 20, 15, 00, 0)

    # hist = api.GetPriceHistory(symbol=args.symbol,
    #                            period=1, periodType='day',
    #                            frequency=1, frequencyType='minute',
    #                            startDate=start, endDate=end)
    hist = api.GetPriceHistory(symbol=args.symbol,
                               period=1,
                               periodType='day',
                               frequency=5,
                               frequencyType='minute',
                               startDate=start,
                               endDate=end)
    if 'error' in hist:
        logging.error(f"Error: {hist}")
        return
    if hist.get('empty', False):
        logging.error(f"Error: {hist}")
        return

    candle = price_history_to_arrays(hist)
    print(len(candle))
예제 #7
0
def main():
    """Compute various vol estimates."""
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    # Fetch call chain for underlying.
    hist = api.GetPriceHistory(symbol='SPY',
                               frequency=1,
                               frequencyType='daily',
                               period=2,
                               periodType='year')
    candle = price_history_to_arrays(hist)

    # Compute historical volatility estimates and centile of vol distribution of
    # underlying over various time periods.
    for days in [7, 15, 30, 60, 90, 120, 180, 365, None]:
        centiles = True
        if days is None:
            centiles = False
            days = candle.datetime.shape[0]
        vol = historical_volatility(candle.datetime[-days:],
                                    candle.close[-days:])

        if centiles:
            _, vols = historical_volatility_dist(candle.datetime, candle.close,
                                                 days)
            assert len(vols) > 0
            meanvol = numpy.mean(vols)
            stdvol = numpy.std(vols)
            centile = norm.cdf(vol, meanvol, stdvol)
            print("Vol over {:3} days: {:8.2f}"
                  "  (centile: {:5.1%} - {:.1f}~{:.1f})".format(
                      days, vol, centile, meanvol, stdvol))
        else:
            print("Vol over {:3} days: {:8.2f}".format(days, vol))
예제 #8
0
def main():
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    accountId = get_first_account_api(api)

    # prefs = api.GetPreferences(accountId=accountId)
    # pprint(prefs)

    # keys = api.GetStreamerSubscriptionKeys(accountIds=accountId)
    # pprint(keys)

    # prin = api.GetUserPrincipals(fields='surrogateIds')
    # pprint(prin)

    # txns = api.GetTransactions(accountId=accountId)
    # pprint(txns)

    # instruments = api.SearchInstruments(symbol='SPY', projection='symbol-search')
    # hours = api.GetHoursMultipleMarkets()
    # hours = api.GetHoursMultipleMarkets()
    # pprint.pprint(hours)

    # for o in get_options_values(api):
    #     print(o)

    quotes = api.GetQuotes(symbol='VTI')
    pprint(quotes)

    hist = api.GetPriceHistory(symbol='VTI')
    pprint(hist)
예제 #9
0
def main():
    """Cancel all orders."""
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)
    args = parser.parse_args()
    config = ameritrade.config_from_args(args, readonly=False)
    api = ameritrade.open(config)

    orders = api.GetOrdersByQuery()
    cancel_orders = []
    for order in orders:
        if order['status'] != 'QUEUED':
            continue
        cancel_orders.append(order)
        print(order_str(order))
    print("Cancel all orders [y/n]?")
    response = input()
    if response != 'y':
        print("Exiting without canceling.")
        return
    for order in cancel_orders:
        print("Canceling order {}".format(order['orderId']))
        status = api.CancelOrder(**keep(order, {'accountId', 'orderId'}))
        pprint.pprint(status)
예제 #10
0
def main():
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-8s: %(message)s')
    parser = argparse.ArgumentParser(description=__doc__.strip())
    ameritrade.add_args(parser)

    parser.add_argument(
        '-s',
        '--underlying',
        '--stock',
        action='store',
        default='$XSP.X',  # E-mini S&P 500 Futures
        help="Name of the underlying to use.")

    parser.add_argument(
        '-v',
        '--volatility',
        '--vol',
        action='store',
        type=float,
        help=("Volatility assumption (if not present, use single estimate "
              "of implied vol)."))

    parser.add_argument(
        '-p',
        '--pvalue',
        action='store',
        type=float,
        default=2.0,  # 95%
        help="Minimum p-value to use.")

    parser.add_argument(
        '-m',
        '--near-margin',
        action='store',
        type=float,
        help=("Fixed (over time) minimum margin (in pct) away from "
              "the underlying."))

    parser.add_argument(
        '-f',
        '--filter',
        action='store',
        help="Filter on the description field (for Weekly or Monthly)")

    args = parser.parse_args()
    config = ameritrade.config_from_args(args)
    api = ameritrade.open(config)

    # Fetch call chain.
    fromDate = datetime.date.today() + datetime.timedelta(days=5)
    toDate = datetime.date.today() + datetime.timedelta(days=45)
    chain = api.GetOptionChain(symbol=args.underlying,
                               strategy='SINGLE',
                               contractType='CALL',
                               range='SAK',
                               fromDate=fromDate,
                               toDate=toDate)
    if chain['status'] != 'SUCCESS':
        logging.error(chain)
        return

    tbl = get_candidates(chain, args)
    if args.filter:
        tbl = tbl.filter(lambda row: re.search(args.filter, row.description))

    print('Options for {}: {}'.format(chain['symbol'],
                                      chain['underlyingPrice']))
    print(tbl)
예제 #11
0
def main():
    argparser = argparse.ArgumentParser()
    ameritrade.add_args(argparser)

    argparser.add_argument('-i',
                           '--ignore-errors',
                           dest='raise_error',
                           action='store_false',
                           default=True,
                           help="Raise an error on unhandled messages")
    argparser.add_argument(
        '-J',
        '--debug-file',
        '--json',
        action='store',
        help="Debug filename where to strore al the raw JSON")
    argparser.add_argument(
        '-j',
        '--debug-transaction',
        action='store',
        type=int,
        help="Process a single transaction and print debugging data about it.")

    argparser.add_argument('-e',
                           '--end-date',
                           action='store',
                           help="Period of end date minus one year.")

    argparser.add_argument('-B',
                           '--no-booking',
                           dest='booking',
                           action='store_false',
                           default=True,
                           help="Do booking to resolve lots.")

    argparser.add_argument('-l',
                           '--ledger',
                           action='store',
                           help=("Beancount ledger to remove already imported "
                                 "transactions (optional)."))

    argparser.add_argument(
        '-g',
        '--group-by-underlying',
        action='store_true',
        help=("Group the transaction output by corresponding "
              "underlying. This is great for options."))

    args = argparser.parse_args()

    # Open a connection and figure out the main account.
    api = ameritrade.open(ameritrade.config_from_args(args))
    accountId = utils.GetMainAccount(api)
    positions = utils.GetPositions(api, accountId)

    # Fetch transactions.
    # Note that the following arguments are also honored:
    #   endDate=datetime.date.today().isoformat())
    #   startDate='2014-01-01',
    #   endDate='2015-01-01')
    if args.end_date:
        end_date = parser.parse(args.end_date).date()
        start_date = end_date - datetime.timedelta(days=364)
        start = start_date.isoformat()
        end = end_date.isoformat()
    else:
        start = end = None
    txns = api.GetTransactions(accountId=accountId,
                               startDate=start,
                               endDate=end)
    if isinstance(txns, dict):
        pprint(txns, sys.stderr)
        return
    txns.reverse()

    # Optionally write out the raw original content downloaded to a file.
    if args.debug_file:
        with open(args.debug, 'w') as ofile:
            ofile.write(pformat(txns))

    # Process each of the transactions.
    entries = []
    balances = collections.defaultdict(inventory.Inventory)
    commodities = {}
    for txn in txns:
        if args.debug_transaction and txn[
                'transactionId'] != args.debug_transaction:
            continue
        else:
            pprint.pprint(txn)

        # print('{:30} {}'.format(txn['type'], txn['description'])); continue
        dispatch_entries = RunDispatch(txn, balances, commodities,
                                       args.raise_error)
        if dispatch_entries:
            entries.extend(dispatch_entries)

            # Update a balance account of just the units.
            #
            # This is only here so that the options removal can figure out which
            # side is the reduction side and what sign to use on the position
            # change. Ideally the API would provide a side indication and we
            # wouldn't have to maintain any state at alll. {492fa5292636}
            for entry in data.filter_txns(dispatch_entries):
                for posting in entry.postings:
                    balance = balances[posting.account]
                    if posting.units is not None:
                        balance.add_amount(posting.units)

    # Add a final balance entry.
    balance_entry = CreateBalance(api, accountId)
    if balance_entry:
        entries.append(balance_entry)

    if args.booking:
        # Book the entries.
        entries, balance_errors = booking.book(entries,
                                               OPTIONS_DEFAULTS.copy())
        if balance_errors:
            printer.print_errors(balance_errors)

        # Remove dates on reductions when they have no prices. This is an
        # artifact of not being able to pass in prior balance state to the
        # booking code, which we will fix in v3.
        entries = RemoveDateReductions(entries)

        # Match up the trades we can in this subset of the history and pair them up
        # with a common random id.
        entries, balances = MatchTrades(entries)

        # Add zero prices for expired options for which we still have non-zero
        # positions.
        entries.extend(GetExpiredOptionsPrices(positions, balances))

    # If a Beancount ledger has been specified, open it, read it in, and remove
    # all the transactions up to the latest one with the transaction id (as a
    # link) that's present in the ledger.
    if args.ledger:
        ledger_entries, _, __ = loader.load_file(args.ledger)

        # Find the date of the last transaction in the ledger with a TD
        # transaction id, and the full set of links to remove.
        links = set()
        last_date = None
        for entry in data.filter_txns(ledger_entries):
            for link in (entry.links or {}):
                if re.match(r"td-\d{9,}", link):
                    links.add(link)
                    last_date = entry.date

        # Remove all the transactions already present in the ledger.
        #
        # Also remove all the non-transactions with a date before that of the
        # last linked one that was found. This allows us to remove Price and
        # Commodity directives. (In v3, when links are available on every
        # directive, we can just use the links.)
        entries = [
            entry for entry in entries
            if ((isinstance(entry, data.Transaction) and not entry.links
                 & links) or (not isinstance(entry, data.Transaction)
                              and entry.date >= last_date))
        ]

    if args.group_by_underlying:
        # Group the transactions by their underlying, with org-mode separators.
        groups = GroupByUnderlying(entries)
        for (has_option, currency), group_entries in sorted(groups.items()):
            header = currency or "General"
            if has_option:
                header = "Options: {}".format(header)
            print("** {}".format(header))
            print()
            printer.print_entries(data.sorted(group_entries), file=sys.stdout)
            print()
            print()
    else:
        # Render all the entries chronologically (the default).
        sentries = SortCommodityFirst(entries)
        printer.print_entries(sentries, file=sys.stdout)