From 376e67934d07e31920f39a1e8d1bc7c13328500b Mon Sep 17 00:00:00 2001 From: Gabe Appleton Date: Sun, 4 Sep 2022 17:41:10 -0400 Subject: [PATCH] General refactoring of code --- MarketInfoBot.sqlite3 | Bin 155648 -> 159744 bytes MarketInfoPersonal.sqlite3 | Bin 311296 -> 323584 bytes daemon.sh | 2 +- example.json | 200 ++++++++----------------------- example_json.py | 63 ++++++---- src/__init__.py | 21 ++++ src/__main__.py | 128 ++++++++++++++++++++ example.py => src/application.py | 127 +------------------- src/market.py | 4 +- src/rule.py | 19 --- 10 files changed, 242 insertions(+), 322 deletions(-) create mode 100644 src/__main__.py rename example.py => src/application.py (57%) diff --git a/MarketInfoBot.sqlite3 b/MarketInfoBot.sqlite3 index fc74589825d49b7d6dd986ee47763452c9d35664..af3950d3d3fc8b483b49124d6f063eaafa1f1d42 100644 GIT binary patch delta 25584 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 OL?#l8Wb!>RFZv$_@xKcI delta 10103 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 ZZW5(+IZ$HlT@)&rT%l5_o_VF>@^5;pf%gCa diff --git a/MarketInfoPersonal.sqlite3 b/MarketInfoPersonal.sqlite3 index b574c3e01fe09bdcd9f1aad7787cee4bd75a5f4c..5deac1fd25098b5a255b544b0ca1827d7fe07a35 100644 GIT binary patch delta 30101 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¥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 delta 23389 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 o69m%>#vR5PrV9-Hjx`- to check now, and twice to exit before next loop." hour=0 diff --git a/example.json b/example.json index f56c2eb..bf6f128 100644 --- a/example.json +++ b/example.json @@ -1,153 +1,49 @@ [ - { - "manifold": { - "outcomeType": "BINARY", - "question": "Is supersymmetry correct?", - "description": { - "type": "doc", - "content": [{ - "type": "paragraph", - "content": [{ - "type": "text", - "text": "https://en.wikipedia.org/wiki/Supersymmetry", - "marks": [{ - "type": "link", - "attrs": { - "href": "https://en.wikipedia.org/wiki/Supersymmetry", - "target": "_blank", - "class": null - } - }] - }] - }] - }, - "closeTime": "2100-12-31T11:59:59", - - "initialProb": 50, - - "minValue": null, - "maxValue": null, - "isLogScale": null, - "initialValue": null, - "groups": ["Physics Forecasting", "Olivia"] - }, - "time_rules": [ - ["ResolveAtTime", { - "resolve_at": "2100-12-31T11:59:59" - }] - ], - "value_rules": [ - ["RoundValueRule", {}] - ], - "notes": "", - "initial_values": {} - }, - { - "manifold": { - "outcomeType": "PSEUDO_NUMERIC", - "question": "When will the next mission to Jupiter be launched?", - "description": { - "type": "doc", - "content": [{ - "type": "paragraph", - "content": [{ - "type": "text", - "text": "Resolves to the fractional year at which a mission to the Jovian system is launched. This includes flyby missions, orbiters, landers, or any of these types of mission to a moon in orbit of Jupiter. This does not include any bodies which are in resonance with Jupiter but not in orbit." - }] - }], - "processed": true - }, - "closeTime": "2100-12-31T11:59:59", - - "initialProb": null, - - "minValue": 2023, - "maxValue": 2100, - "isLogScale": true, - "initialValue": 2035, - "groups": ["Space", "Olivia"] - }, - "time_rules": [ - ["ResolveAtTime", { - "resolve_at": "2100-12-31T11:59:59" - }] - ], - "value_rules": [ - ["CurrentValueRule", {}] - ], - "notes": "", - "initial_values": {} - }, - { - "manifold": { - "outcomeType": "PSEUDO_NUMERIC", - "question": "When will the next mission to a minor body between Mars and the Kuiper Belt be launched?", - "description": { - "type": "doc", - "content": [{ - "type": "paragraph", - "content": [{ - "type": "text", - "text": "Resolves to the fractional year at which a mission to the Neptunian system is launched. This includes flyby missions, orbiters, landers, or miners. This does not include any bodies which are in orbit of a major planet." - }] - }], - "processed": true - }, - "closeTime": "2100-12-31T11:59:59", - - "initialProb": null, - - "minValue": 2023, - "maxValue": 2100, - "isLogScale": true, - "initialValue": 2035, - "groups": ["Space", "Olivia"] - }, - "time_rules": [ - ["ResolveAtTime", { - "resolve_at": "2100-12-31T11:59:59" - }] - ], - "value_rules": [ - ["CurrentValueRule", {}] - ], - "notes": "", - "initial_values": {} - }, - { - "manifold": { - "outcomeType": "PSEUDO_NUMERIC", - "question": "When will the next mission to Kuiper Belt be launched?", - "description": { - "type": "doc", - "content": [{ - "type": "paragraph", - "content": [{ - "type": "text", - "text": "Resolves to the fractional year at which a mission to the Kuiper Belt is launched. This includes any body in the Kuiper Belt that is not considered a major planet or in orbit of a major planet." - }] - }], - "processed": true - }, - "closeTime": "2100-12-31T11:59:59", - - "initialProb": null, - - "minValue": 2023, - "maxValue": 2100, - "isLogScale": true, - "initialValue": 2035, - "groups": ["Space", "Olivia"] - }, - "time_rules": [ - ["ResolveAtTime", { - "resolve_at": "2100-12-31T11:59:59" - }] - ], - "value_rules": [ - ["CurrentValueRule", {}] - ], - "notes": "", - "initial_values": {} - } -] + { + "manifold": { + "outcomeType": "PSEUDO_NUMERIC", + "question": "When will the next mission to Kuiper Belt be launched?", + "description": { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Resolves to the fractional year at which a mission to the Kuiper Belt is launched. This includes any body in the Kuiper Belt that is not considered a major planet or in orbit of a major planet." + } + ] + } + ], + "processed": true + }, + "closeTime": "2100-12-31T11:59:59", + "initialProb": null, + "minValue": 2023, + "maxValue": 2100, + "isLogScale": true, + "initialValue": 2035, + "groups": [ + "Space", + "Olivia" + ] + }, + "time_rules": [ + [ + "ResolveAtTime", + { + "resolve_at": "2100-12-31T11:59:59" + } + ] + ], + "value_rules": [ + [ + "CurrentValueRule", + {} + ] + ], + "notes": "", + "initial_values": {} + } +] \ No newline at end of file diff --git a/example_json.py b/example_json.py index 5c9f17e..76adea0 100644 --- a/example_json.py +++ b/example_json.py @@ -5,9 +5,9 @@ from json import dump, load from re import match from typing import Any, Dict, List, Literal, Optional, Union -from src import rule -from src.rule import explain_abstract, DoResolveRule, ResolutionValueRule -from src.market import Market, get_client +from src import rule, explain_abstract +from src.rule import DoResolveRule, ResolutionValueRule +from src.market import get_client, Market from example import register_db from pymanifold.types import DictDeserializable @@ -21,16 +21,19 @@ def main(): for mkt in obj.copy(): my_mkt = CreationRequest.from_dict(mkt).create() db.execute("INSERT INTO markets VALUES ( (SELECT MAX(id)+1 from markets), ?, 3, NULL);", (my_mkt, )) + ((new_id, ), ) = db.execute("SELECT MAX(id) from markets;") + print(f"Added as ID {new_id}") + print(my_mkt.market.url) obj.remove(mkt) finally: db.commit() db.close() with open('example.json', 'w') as f: - dump(obj, default=date_serialization_hook) + dump(obj, f, default=date_serialization_hook, indent="\t") def date_serialization_hook(obj): - """JSON serializer for objects not serializable by default json code""" + """JSON serializer for objects not serializable by default json code.""" if isinstance(obj, (datetime, date)): return obj.isoformat() raise TypeError(f"Type ${type(obj)} not serializable") @@ -56,13 +59,13 @@ class ManifoldRequest(DictDeserializable): description: Union[str, Any] closeTime: int - initialProb: Optional[float] # Note: probability is multiplied by 100, may only allow integers in binary market + initialProb: Optional[float] = None # Note: probability is multiplied by 100, may only allow integers - minValue: Optional[float] - maxValue: Optional[float] - isLogScale: Optional[bool] - initialValue: Optional[float] - groups: List[str] = field(default_factory=list) + minValue: Optional[float] = None + maxValue: Optional[float] = None + isLogScale: Optional[bool] = None + initialValue: Optional[float] = None + tags: List[str] = field(default_factory=list) def __post_init__(self): if self.outcomeType == "BINARY": @@ -91,20 +94,27 @@ class CreationRequest: notes: str = "" initial_values: Dict[str, int] = field(default_factory=dict) - def __postinit__(self): + def __post_init__(self): if not self.manifold.description.get("processed"): - for paragraph in explain_abstract( + explanation = "\n" + explain_abstract( time_rules=self.time_rules, value_rules=self.value_rules - ).splitlines(): - # if not paragraph: - # continue - self.manifold.description["content"].append({ - "type": "paragraph", - "content": [{ - "type": "text", - "text": paragraph - }] - }) + ) + for paragraph in explanation.splitlines(): + if paragraph: + if paragraph.startswith(" "): + for idx, character in enumerate(paragraph): + if character != " ": + break + paragraph = paragraph.replace(" ", " ", idx) + self.manifold.description["content"].append({ + "type": "paragraph", + "content": [{ + "type": "text", + "text": paragraph + }] + }) + else: + self.manifold.description["content"].append({"type": "paragraph"}) self.manifold.description["processed"] = True @classmethod @@ -139,7 +149,12 @@ class CreationRequest: else: raise ValueError() - return Market(market, do_resolve_rules=self.time_rules, resolve_to_rules=self.value_rules, notes=self.notes) + return Market( + client.get_market_by_id(market.id), + do_resolve_rules=self.time_rules, + resolve_to_rules=self.value_rules, + notes=self.notes + ) if __name__ == '__main__': diff --git a/src/__init__.py b/src/__init__.py index 8a2b99d..389a1ff 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -47,6 +47,27 @@ def require_env(*env: str): return bar +def explain_abstract(**kwargs) -> str: + """Explain how the market will resolve and decide to resolve.""" + ret = "This market will resolve if any of the following are true:\n" + for rule_ in kwargs["time_rules"]: + ret += rule_.explain_abstract(**kwargs) + ret += ("\nIt will resolve based on the following decision tree:\n" + "- If the human operator agrees:\n") + for rule_ in kwargs["value_rules"]: + ret += rule_.explain_abstract(indent=1, **kwargs) + ret += ( + "- Otherwise, a manually provided value\n\n" + "Note that the bot operator reserves the right to resolve contrary to the purely automated rules to " + "preserve the spirit of the market. All resolutions are first verified by the human operator." + "\n\n" + "The operator also reserves the right to trade on this market unless otherwise specified. Even if " + "otherwise specified, the operator reserves the right to buy shares for subsidy or to trade for the " + "purposes of cashing out liquidity.\n" + ) + return ret + + class Rule(DictDeserializable): """The basic unit of market automation, rules defmine how a market should react to given events.""" diff --git a/src/__main__.py b/src/__main__.py new file mode 100644 index 0000000..743ef49 --- /dev/null +++ b/src/__main__.py @@ -0,0 +1,128 @@ +from argparse import ArgumentParser +from datetime import datetime +from logging import basicConfig, getLogger, DEBUG, INFO +from os import getenv +from typing import cast, Optional, Tuple + +from .application import register_db, main +from . import market, rule + +# Enable logging +basicConfig( + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + level=(INFO if not getenv("DEBUG") else DEBUG), + filename=getenv("LogFile"), +) +logger = getLogger(__name__) + +parser = ArgumentParser() +parser.add_argument('-s', '--add-slug', action='store', dest='slug') +parser.add_argument('-i', '--add-id', action='store', dest='id_') +parser.add_argument('-u', '--add-url', action='store', dest='url') +parser.add_argument('-c', '--check-rate', action='store', dest='rate', help='Check rate in hours') + +parser.add_argument('-mi', '--min', action='store', + help="Only used for numeric markets, until they add this to the API") +parser.add_argument('-ma', '--max', action='store', + help="Only used for numeric markets, until they add this to the API") +parser.add_argument('-ls', '--log_scale', action='store_true', dest='isLogScale', + help="Only used for numeric markets, until they add this to the API") + +parser.add_argument('-r', '--refresh', action='store_true', dest='refresh', + help="Ignore time last checked and look at all markets immediately") + +parser.add_argument('-rm', '--remove-id', action='append', dest='rm_id', default=[], + help="Remove a specific market from management. May be repeated.") + +parser.add_argument('-rnd', '--round', action='store_true') +parser.add_argument('-cur', '--current', action='store_true') +parser.add_argument('-rd', '--rel-date', action='store', dest='rel_date', + help='Please give as "year/month/day" or "year-month-day". Used in: poll, git PR') + +parser.add_argument('-pr', '--pull-request', action='store', dest='pr_slug', help='Please give as "owner/repo/num"') +parser.add_argument('-pb', '--pull-binary', action='store_true', dest='pr_bin') + +parser.add_argument('-sk', '--skip', action='store_true') +parser.add_argument('-co', '--console-only', action='store_true') + +parser.add_argument('-rs', '--random-seed', action='store') +parser.add_argument('-rr', '--random-rounds', action='store', type=int, default=1) +parser.add_argument('-ri', '--random-index', action='store_true') +parser.add_argument('-is', '--index-size', action='store', type=int) + +args = parser.parse_args() + +for id_ in args.rm_id: + conn = register_db() + ((mkt, ), ) = conn.execute( + "SELECT market FROM markets WHERE id = ?;", + (id_, ) + ) + if input(f'Are you sure you want to remove {id_}: "{mkt.market.question}" (y/N)?').lower().startswith('y'): + conn.execute( + "DELETE FROM markets WHERE id = ?;", + (id_, ) + ) + conn.commit() + logger.info(f"{id_} removed from db") + conn.close() + +if any((args.slug, args.id_, args.url)): + if args.url: + args.slug = args.url.split('/')[-1] + + if args.slug: + mkt = market.Market.from_slug(args.slug) + else: + mkt = market.Market.from_id(args.id) + + if args.rel_date: + sections = args.rel_date.split('/') + if len(sections) == 1: + sections = args.rel_date.split('-') + try: + date: Optional[Tuple[int, int, int]] = tuple(int(x) for x in sections) # type: ignore[assignment] + except ValueError: + raise + else: + date = None + + if args.random_index: + mkt.resolve_to_rules.append( + rule.ResolveRandomIndex(args.random_seed, size=args.index_size, rounds=args.random_rounds) + ) + + if args.round: + mkt.resolve_to_rules.append(rule.RoundValueRule()) + if args.current: + mkt.resolve_to_rules.append(rule.CurrentValueRule()) + + if args.pr_slug: + pr_ = list(args.pr_slug.split('/')) + pr_[-1] = int(pr_[-1]) + pr = cast(Tuple[str, str, int], tuple(pr_)) + mkt.do_resolve_rules.append(rule.ResolveWithPR(*pr)) + if date: + mkt.resolve_to_rules.append(rule.ResolveToPRDelta(*pr, datetime(*date))) + elif args.pr_bin: + mkt.resolve_to_rules.append(rule.ResolveToPR(*pr)) + else: + raise ValueError("No resolve rule provided") + + if not mkt.do_resolve_rules: + if not date: + raise ValueError("No resolve date provided") + mkt.do_resolve_rules.append(rule.ResolveAtTime(datetime(*date))) + + conn = register_db() + + idx = max(((0, ), *conn.execute("SELECT id FROM markets;")))[0] + 1 + conn.execute("INSERT INTO markets values (?, ?, ?, ?);", (idx, mkt, 1, None)) + conn.commit() + + print(msg := f"Successfully added as ID {idx}!") + logger.info(msg) + conn.close() + +if not args.skip: + main(args.refresh, args.console_only) diff --git a/example.py b/src/application.py similarity index 57% rename from example.py rename to src/application.py index ef33eb3..2cdbf58 100644 --- a/example.py +++ b/src/application.py @@ -1,13 +1,12 @@ -from argparse import ArgumentParser from asyncio import get_event_loop, new_event_loop, set_event_loop from dataclasses import dataclass from datetime import datetime, timedelta from enum import IntEnum -from logging import basicConfig, getLogger, DEBUG, INFO +from logging import getLogger from pathlib import Path from os import getenv from sqlite3 import connect, PARSE_COLNAMES, PARSE_DECLTYPES -from typing import cast, Optional, Tuple +from typing import cast from telegram import __version__ as TG_VER @@ -26,14 +25,8 @@ if __version_info__ < (20, 0, 0, "alpha", 1): from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update from telegram.ext import Application, CallbackQueryHandler, ContextTypes -from src import (market, require_env, rule) +from src import market, require_env -# Enable logging -basicConfig( - format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", - level=(INFO if not getenv("DEBUG") else DEBUG), - filename=getenv("LogFile"), -) logger = getLogger(__name__) @@ -195,117 +188,3 @@ def main(refresh: bool = False, console_only: bool = False): ) conn.commit() conn.close() - - -if __name__ == '__main__': - parser = ArgumentParser() - parser.add_argument('-s', '--add-slug', action='store', dest='slug') - parser.add_argument('-i', '--add-id', action='store', dest='id_') - parser.add_argument('-u', '--add-url', action='store', dest='url') - parser.add_argument('-c', '--check-rate', action='store', dest='rate', help='Check rate in hours') - - parser.add_argument('-mi', '--min', action='store', - help="Only used for numeric markets, until they add this to the API") - parser.add_argument('-ma', '--max', action='store', - help="Only used for numeric markets, until they add this to the API") - parser.add_argument('-ls', '--log_scale', action='store_true', dest='isLogScale', - help="Only used for numeric markets, until they add this to the API") - - parser.add_argument('-r', '--refresh', action='store_true', dest='refresh', - help="Ignore time last checked and look at all markets immediately") - - parser.add_argument('-rm', '--remove-id', action='append', dest='rm_id', default=[], - help="Remove a specific market from management. May be repeated.") - - parser.add_argument('-rnd', '--round', action='store_true') - parser.add_argument('-cur', '--current', action='store_true') - parser.add_argument('-rd', '--rel-date', action='store', dest='rel_date', - help='Please give as "year/month/day" or "year-month-day". Used in: poll, git PR') - - parser.add_argument('-pr', '--pull-request', action='store', dest='pr_slug', help='Please give as "owner/repo/num"') - parser.add_argument('-pb', '--pull-binary', action='store_true', dest='pr_bin') - - parser.add_argument('-sk', '--skip', action='store_true') - parser.add_argument('-co', '--console-only', action='store_true') - - parser.add_argument('-rs', '--random-seed', action='store') - parser.add_argument('-rr', '--random-rounds', action='store', type=int, default=1) - parser.add_argument('-ri', '--random-index', action='store_true') - parser.add_argument('-is', '--index-size', action='store', type=int) - - args = parser.parse_args() - - for id_ in args.rm_id: - conn = register_db() - ((mkt, ), ) = conn.execute( - "SELECT market FROM markets WHERE id = ?;", - (id_, ) - ) - if input(f'Are you sure you want to remove {id_}: "{mkt.market.question}" (y/N)?').lower().startswith('y'): - conn.execute( - "DELETE FROM markets WHERE id = ?;", - (id_, ) - ) - conn.commit() - logger.info(f"{id_} removed from db") - conn.close() - - if any((args.slug, args.id_, args.url)): - if args.url: - args.slug = args.url.split('/')[-1] - - if args.slug: - mkt = market.Market.from_slug(args.slug) - else: - mkt = market.Market.from_id(args.id) - - if args.rel_date: - sections = args.rel_date.split('/') - if len(sections) == 1: - sections = args.rel_date.split('-') - try: - date: Optional[Tuple[int, int, int]] = tuple(int(x) for x in sections) # type: ignore[assignment] - except ValueError: - raise - else: - date = None - - if args.random_index: - mkt.resolve_to_rules.append( - rule.ResolveRandomIndex(args.random_seed, size=args.index_size, rounds=args.random_rounds) - ) - - if args.round: - mkt.resolve_to_rules.append(rule.RoundValueRule()) - if args.current: - mkt.resolve_to_rules.append(rule.CurrentValueRule()) - - if args.pr_slug: - pr_ = list(args.pr_slug.split('/')) - pr_[-1] = int(pr_[-1]) - pr = cast(Tuple[str, str, int], tuple(pr_)) - mkt.do_resolve_rules.append(rule.ResolveWithPR(*pr)) - if date: - mkt.resolve_to_rules.append(rule.ResolveToPRDelta(*pr, datetime(*date))) - elif args.pr_bin: - mkt.resolve_to_rules.append(rule.ResolveToPR(*pr)) - else: - raise ValueError("No resolve rule provided") - - if not mkt.do_resolve_rules: - if not date: - raise ValueError("No resolve date provided") - mkt.do_resolve_rules.append(rule.ResolveAtTime(datetime(*date))) - - conn = register_db() - - idx = max(((0, ), *conn.execute("SELECT id FROM markets;")))[0] + 1 - conn.execute("INSERT INTO markets values (?, ?, ?, ?);", (idx, mkt, 1, None)) - conn.commit() - - print(msg := f"Successfully added as ID {idx}!") - logger.info(msg) - conn.close() - - if not args.skip: - main(args.refresh, args.console_only) diff --git a/src/market.py b/src/market.py index fa5fd6d..784df74 100644 --- a/src/market.py +++ b/src/market.py @@ -10,8 +10,8 @@ from typing import Any, Dict, List, Union from pymanifold import ManifoldClient from pymanifold.types import Market as APIMarket -from . import require_env -from .rule import explain_abstract, DoResolveRule, ResolutionValueRule +from . import explain_abstract, require_env +from .rule import DoResolveRule, ResolutionValueRule @lru_cache diff --git a/src/rule.py b/src/rule.py index abc80d2..dc662f0 100644 --- a/src/rule.py +++ b/src/rule.py @@ -11,25 +11,6 @@ import requests from . import require_env, Rule -def explain_abstract(**kwargs) -> str: - """Explain how the market will resolve and decide to resolve.""" - ret = "This market will resolve if any of the following are true:\n" - for rule in kwargs["time_rules"]: - ret += rule.explain_abstract(**kwargs) - ret += "\nIt will resolve based on the following decision tree:\n" - for rule in kwargs["value_rules"]: - ret += rule.explain_abstract(**kwargs) - ret += ( - "\nNote that the bot operator reserves the right to resolve contrary to the purely automated rules to " - "preserve the spirit of the market. All resolutions are first verified by the human operator." - "\n\n" - "The operator also reserves the right to trade on this market unless otherwise specified. Even if " - "otherwise specified, the operator reserves the right to buy shares for subsidy or to trade for the " - "purposes of cashing out liquidity.\n" - ) - return ret - - class DoResolveRule(Rule): """The subtype of rule which determines if a market should resolve, returning a bool."""