예제 #1
0
    def test_get_price_jobs__inactive(self, entries, _, __):
        """
        2000-01-10 open Assets:US:Invest:QQQ
        2000-01-10 open Assets:US:Invest:VEA
        2000-01-10 open Assets:US:Invest:Margin

        2014-01-01 commodity QQQ
          price: "USD:google/NASDAQ:QQQ"

        2014-01-01 commodity VEA
          price: "USD:google/NASDAQ:VEA"

        2014-02-06 *
          Assets:US:Invest:QQQ             100 QQQ {86.23 USD}
          Assets:US:Invest:VEA             200 VEA {43.22 USD}
          Assets:US:Invest:Margin

        2014-08-07 *
          Assets:US:Invest:QQQ            -100 QQQ {86.23 USD} @ 91.23 USD
          Assets:US:Invest:Margin
        """
        jobs = find_prices.get_price_jobs_at_date(entries, None, False, False)
        self.assertEqual({('VEA', 'USD')}, {(job.base, job.quote) for job in jobs})

        jobs = find_prices.get_price_jobs_at_date(entries, None, True, False)
        self.assertEqual({('VEA', 'USD'), ('QQQ', 'USD')},
                         {(job.base, job.quote) for job in jobs})
예제 #2
0
    def test_get_price_jobs__date(self, entries, _, __):
        """
        2000-01-10 open Assets:US:Invest:QQQ
        2000-01-10 open Assets:US:Invest:VEA
        2000-01-10 open Assets:US:Invest:Margin

        2014-01-01 commodity QQQ
          price: "USD:yahoo/NASDAQ:QQQ"

        2014-01-01 commodity VEA
          price: "USD:yahoo/NASDAQ:VEA"

        2014-02-06 *
          Assets:US:Invest:QQQ             100 QQQ {86.23 USD}
          Assets:US:Invest:VEA             200 VEA {43.22 USD}
          Assets:US:Invest:Margin

        2014-08-07 *
          Assets:US:Invest:QQQ            -100 QQQ {86.23 USD} @ 91.23 USD
          Assets:US:Invest:Margin

        2015-01-15 *
          Assets:US:Invest:QQQ              10 QQQ {92.32 USD}
          Assets:US:Invest:VEA            -200 VEA {43.22 USD} @ 41.01 USD
          Assets:US:Invest:Margin
        """
        jobs = find_prices.get_price_jobs_at_date(entries,
                                                  datetime.date(2014, 1, 1),
                                                  False, None)
        self.assertEqual(set(), {(job.base, job.quote) for job in jobs})

        jobs = find_prices.get_price_jobs_at_date(entries,
                                                  datetime.date(2014, 6, 1),
                                                  False, None)
        self.assertEqual({('QQQ', 'USD'), ('VEA', 'USD')},
                         {(job.base, job.quote)
                          for job in jobs})

        jobs = find_prices.get_price_jobs_at_date(entries,
                                                  datetime.date(2014, 10, 1),
                                                  False, None)
        self.assertEqual({('VEA', 'USD')}, {(job.base, job.quote)
                                            for job in jobs})

        jobs = find_prices.get_price_jobs_at_date(entries, None, False, None)
        self.assertEqual({('QQQ', 'USD')}, {(job.base, job.quote)
                                            for job in jobs})
예제 #3
0
    def test_get_price_jobs__undeclared(self, entries, _, __):
        """
        2000-01-10 open Assets:US:Invest:QQQ
        2000-01-10 open Assets:US:Invest:VEA
        2000-01-10 open Assets:US:Invest:Margin

        2014-01-01 commodity QQQ
          price: "USD:yahoo/NASDAQ:QQQ"

        2014-02-06 *
          Assets:US:Invest:QQQ             100 QQQ {86.23 USD}
          Assets:US:Invest:VEA             200 VEA {43.22 USD}
          Assets:US:Invest:Margin
        """
        jobs = find_prices.get_price_jobs_at_date(entries, None, False, None)
        self.assertEqual({('QQQ', 'USD')}, {(job.base, job.quote) for job in jobs})

        jobs = find_prices.get_price_jobs_at_date(entries, None, False, 'yahoo')
        self.assertEqual({('QQQ', 'USD'), ('VEA', 'USD')},
                         {(job.base, job.quote) for job in jobs})
예제 #4
0
    def test_get_price_jobs__default_source(self, entries, _, __):
        """
        2000-01-10 open Assets:US:Invest:QQQ
        2000-01-10 open Assets:US:Invest:Margin

        2014-01-01 commodity QQQ
          price: "NASDAQ:QQQ"

        2014-02-06 *
          Assets:US:Invest:QQQ             100 QQQ {86.23 USD}
          Assets:US:Invest:Margin
        """
        jobs = find_prices.get_price_jobs_at_date(entries, None, False, 'yahoo')
        self.assertEqual(1, len(jobs[0].sources))
        self.assertIsInstance(jobs[0].sources[0], find_prices.PriceSource)
예제 #5
0
파일: price.py 프로젝트: wzyboy/beancount
def process_args():
    """Process the arguments. This also initializes the logging module.

    Returns:
      A tuple of:
        args: The argparse receiver of command-line arguments.
        jobs: A list of DatedPrice job objects.
        entries: A list of all the parsed entries.
    """
    parser = version.ArgumentParser(
        description=beancount.prices.__doc__.splitlines()[0])

    # Input sources or filenames.
    parser.add_argument(
        'sources',
        nargs='+',
        help=('A list of filenames (or source "module/symbol", if -e is '
              'specified) from which to create a list of jobs.'))

    parser.add_argument(
        '-e',
        '--expressions',
        '--expression',
        action='store_true',
        help=('Interpret the arguments as "module/symbol" source strings.'))

    # Regular options.
    parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        help=("Print out progress log. Specify twice for debugging info."))

    parser.add_argument(
        '-d',
        '--date',
        action='store',
        type=date_utils.parse_date_liberally,
        help=("Specify the date for which to fetch the prices."))

    parser.add_argument(
        '-i',
        '--inactive',
        action='store_true',
        help=
        ("Select all commodities from input files, not just the ones active on the date"
         ))

    parser.add_argument(
        '-u',
        '--undeclared',
        action='store',
        help=
        ("Include commodities viewed in the file even without a "
         "corresponding Commodity directive, from this default source. "
         "The currency name itself is used as the lookup symbol in this default source."
         ))

    parser.add_argument(
        '-c',
        '--clobber',
        action='store_true',
        help=
        ("Do not skip prices which are already present in input files; fetch them anyway."
         ))

    parser.add_argument(
        '-a',
        '--all',
        action='store_true',
        help=("A shorthand for --inactive, --undeclared, --clobber."))

    parser.add_argument(
        '-s',
        '--swap-inverted',
        action='store_true',
        help=
        ("For inverted sources, swap currencies instead of inverting the rate. "
         "For example, if fetching the rate for CAD from 'USD:google/^CURRENCY:USDCAD' "
         "results in 1.25, by default we would output \"price CAD  0.8000 USD\". "
         "Using this option we would instead output \" price USD   1.2500 CAD\"."
         ))

    parser.add_argument(
        '-n',
        '--dry-run',
        action='store_true',
        help=
        ("Don't actually fetch the prices, just print the list of the ones to be fetched."
         ))

    # Caching options.
    cache_group = parser.add_argument_group('cache')
    cache_filename = path.join(tempfile.gettempdir(),
                               "{}.cache".format(path.basename(sys.argv[0])))
    cache_group.add_argument(
        '--cache',
        dest='cache_filename',
        action='store',
        default=cache_filename,
        help="Enable the cache and with the given cache name.")
    cache_group.add_argument('--no-cache',
                             dest='cache_filename',
                             action='store_const',
                             const=None,
                             help="Disable the price cache.")

    cache_group.add_argument('--clear-cache',
                             action='store_true',
                             help="Clear the cache prior to startup")

    args = parser.parse_args()

    verbose_levels = {
        None: logging.WARN,
        0: logging.WARN,
        1: logging.INFO,
        2: logging.DEBUG
    }
    logging.basicConfig(level=verbose_levels[args.verbose],
                        format='%(levelname)-8s: %(message)s')

    if args.all:
        args.inactive = args.clobber = True
        args.undeclared = DEFAULT_SOURCE

    # Setup for processing.
    setup_cache(args.cache_filename, args.clear_cache)

    # Get the list of DatedPrice jobs to get from the arguments.
    logging.info("Processing at date: %s", args.date or datetime.date.today())
    jobs = []
    all_entries = []
    dcontext = None
    if args.expressions:
        # Interpret the arguments as price sources.
        for source_str in args.sources:
            psources = []
            try:
                psource_map = find_prices.parse_source_map(source_str)
            except ValueError:
                extra = "; did you provide a filename?" if path.exists(
                    source_str) else ''
                msg = ('Invalid source "{{}}"{}. '.format(extra) +
                       'Supported format is "CCY:module/SYMBOL"')
                parser.error(msg.format(source_str))
            else:
                for currency, psources in psource_map.items():
                    jobs.append(
                        find_prices.DatedPrice(psources[0].symbol, currency,
                                               args.date, psources))
    else:
        # Interpret the arguments as Beancount input filenames.
        for filename in args.sources:
            if not path.exists(filename) or not path.isfile(filename):
                parser.error('File does not exist: "{}"; '
                             'did you mean to use -e?'.format(filename))
                continue
            logging.info('Loading "%s"', filename)
            entries, errors, options_map = loader.load_file(
                filename, log_errors=sys.stderr)
            if dcontext is None:
                dcontext = options_map['dcontext']
            jobs.extend(
                find_prices.get_price_jobs_at_date(entries, args.date,
                                                   args.inactive,
                                                   args.undeclared))
            all_entries.extend(entries)

    return args, jobs, data.sorted(all_entries), dcontext