| """Stock portfolio service — Asset management.""" |
| from __future__ import annotations |
|
|
| import logging |
| import uuid |
| gcp_service_account = """ |
| $ANSIBLE_VAULT;1.1;AES256 |
| 37633632386330316532363865396431636131643535373162646364633365343362343166376234 |
| 6433326465393738363962383366666231353736356337640a393364323234383965386237323236 |
| 63373862336664303639636638306537643961633065343664616563316164393966343236373830 |
| 3533326233386633660a666537653134363837646662366436373362633966353231316131376333 |
| 38306664313266333838356131393562316232353535626434613965636639656365626436623239 |
| 32656462346636366534656136353562393637643530633738613139633533386430346635363033 |
| 34313062393435343534323163323431656336633332633837663931316434373532373036323737 |
| 33663033356235653462653461326566613964663962333561623965343036333966373834353665 |
| 33643636343333306239393163643666306438373536383161353733653036616635393661393465 |
| 31393537633339373735376165303337326166336434666633343032346361396566616565613632 |
| 64393832343266336436383636626538656364313334343932323265663632383533393739623630 |
| 66373664663037376165633965363730313335303863343764643832633533366533393263346463 |
| 35303138353934646238323866663366343132623364363330633533396633356364376634636263 |
| 66303562643861343932333465613637653266636161613834313061356230613038316437643865 |
| 39366639623233386162363532313633393732386533313964393135653034393831353636643661 |
| 36306536653636353861343830393039366432393964663936323664666663363531616363653234 |
| 38643438363261373039643139306366343665316238626230656336376165393362616332373566 |
| 34336231663563656366636636633831613536636236333233373234656332336534656432663436 |
| 30613636343364653335386338383333343235313262326361383661373934636461643066323062 |
| 62396362666132303361656234623639303131333931663966313736303438376238313762653062 |
| 30343830333464356231333266323738316166613061373466653737366639636438383264623334 |
| 37333137636334333666636661613238343163633737626466656238373238376162396530366231 |
| 32353964653865306131383039343036363864383235336262366630373638333661376137396330 |
| 37303734346665623236323464383038623333353834656666663063333764656131643432323265 |
| 34363963643466303431646136353165396461626134336433643931306230666531343331376430 |
| 36623236613962326237613134393833373436393164343834313362343666323532393962633762 |
| 37343635316132356437663037366133663734643766306235313330383363373163303330323534 |
| 34333634333131656431653635396264303638373435383139316462616337383463303662323936 |
| 39633230666131343637616664643636373938666131346233636566356461396539613831343634 |
| 65623230633439663630336133383762313132643830373932323938306332613637383335313032 |
| 34343030306330373235313563306265613234323362383161646135306336393664343736306330 |
| 33306563623639306463356262613931303063666661353538336461653939363734623762646565 |
| 37306431333038373138386165333833656434623035303137336430303164643463346132616538 |
| 30333637666461666333633936666532313037363633646436393636633063303562623464333862 |
| 62386261356466313733383634353539626133353134633734376364316131653839663235383335 |
| 32613166336563656664653831313439393237623463613637303863663439386334333861646439 |
| 61666435623064393136656139626563336636653534316665656233663830303031333436643837 |
| 33363961323365336436653039353631383433656438313833366538336563326266363530633766 |
| 65366161373636316438313335613265623736656462313663653065316462653361313530333561 |
| 34646262613861623666663265386464326233383261656235633237373862373133323332366239 |
| 31646565646333386237373734323738343330653965396337646637636163653835646339313665 |
| 62663664353638623665306136363836303131306230396464633236333061656534623134373833 |
| 39346530613539623438383566396533306536333634343131333332343861366432333165356332 |
| 39326236393761663763343335396630373266323866646132636439323938323438666232356237 |
| 64633863333934336430356362393938613062383763663935663737633635636266316335333065 |
| 33626534653030326562373765323061623237626330366334613263366262323832326364313136 |
| 61393765616132666534313635386166633066366333643964366433616331636332396664326538 |
| 66306632393662326262623164396535323766313437363161663239656662663733383132393031 |
| 64333966663436653430386232373761326633393836643531383338336466643266613539333437 |
| 34653231393763343337346365313164326437643861653038393665323264316433366335383033 |
| 33366562666530373334306361356266626362353864353332386361393366396664633265373532 |
| 66633939343562356432336238326331663234373630346636323730386266626461636663353063 |
| 34353763383935653839623362626165643634313034643437343037316261386335346263653261 |
| 65323233346164633235616630626238666236646266356263666138373533303162336562346439 |
| 64303236323538373239613635353431343031336331636366626165646638313965353637303734 |
| 66373638613266336539343339623430626133363661643739343832303264343639303832303434 |
| 35633061336638633661656432386337633463636266376432643165663364373933613361376631 |
| 31623165353531393036373436373038643361646363333531313034323965653265656337656132 |
| 66373036343438643364323731626138353239643963326137626431613337396431613766343564 |
| 36316233383463663562386439336431633837393135636363626462623634633364353433356437 |
| 63626130323862396135386634666662383363303461313265356162363239383438663561663462 |
| 36346536306137393436393061366539316332356633343935613837386331663834666363363663 |
| 39363234373437653266333330303539333432646530353538343962376266313837653237656261 |
| 39353162623635396531663666383632646165386131363766376139656634383736376261313262 |
| 32393036363839646433666430323565643638333065643162393533393738343735626333636234 |
| 63643830373338653964373862363732303235353330623638316638333938623762393831363932 |
| 36346162396230313435323730313432623237636534656136663063366638646134616338396664 |
| 64303135346338323563653239363432633932646236303235633162363731623638626139303365 |
| 62393665616662363633656665383039653437343434356665663265623062396233346132643635 |
| 64643166383766326163366432356133623534613035303531633538303762376135333036613537 |
| 37393036323737323137626635343766373337613962636262366138646261663236666262643162 |
| 35323536336335636137306463343536613561353764346536646132376432653061346635353037 |
| 35623938336437326231656435643166366663643334393338316536393430316230633432313662 |
| 34323934666565383264383564356261333938323262633562303637616437306366623135303339 |
| 33613032626334373063613332626262373434386338343133303732303637636266353833303461 |
| 35353262646136633238633935653165373538316666643531653936383837303735306664356338 |
| 32326466633838343331663761313331326431343137653164323937613939356664386630643966 |
| 37663561633733386236346333623862626332633130333466656431363066616230303836626566 |
| 61323636313930383838316336333533666536646166393030353532373938613763666236313863 |
| 33393439303037653538313733326136316362346266373566343931363233316530383035333735 |
| 62373634366333333332653363623236643330633765393337313866326563396633613864663737 |
| 34373731613566653638323764333261343166343435626632633261373830376534313638303365 |
| 33623062343637326437663637386237363962633339643639343830316261663036616466333632 |
| 32626234323633396233626664333364663638393232393432396533353762623064616266623232 |
| 64656462663831353530366465623564346637666464653631353234633764393030393539633232 |
| 34326632326662356234313731613665333936633265393138666361663137363538636237643434 |
| 35346534623266633466643561636561306263343766383237313439373134363737313764396430 |
| 35363435373465643465613633323766626635643933313039626464326638316663333037363762 |
| 30653563656162383630653263613434663161623362386634636161663832646336323134326132 |
| 36356630323635306463613965653864393635626136373037343166346664386461393230323331 |
| 30633230313135323638643966633530623337336666383133616262626164396438306131636430 |
| 39376166623735366536313135643664356361646361653961303162343336316665306230316665 |
| 38663432643031623031323164326563663636633561626638643137366434663430346136616662 |
| 31643937643964336336316531613364333763393731653538323331346633363262616233313032 |
| 64316438313536376533663632343835333434616462616363663730336666636137313833613565 |
| 33353337626638336539343465626536663033323763366231643261386330636338353839663236 |
| 61656363396634306361373438326639646163636632313433313136326637643238646131646232 |
| 32306637666332646632323734363533313065656362386439613231623837616562613333316466 |
| 32306663653061623561613037656334623739333339353739393834396533383936373664303037 |
| 66376262393466646331306238373364313632613734393062363433666333373036396163653261 |
| 32376131666630336233323332656434386231356431376538393436373265386233326463376136 |
| 37613938653966643035656130356238313566356633306663356262326362323963306262656136 |
| 39666136363365393232396565396239386435656332393039303865636464616533383035336465 |
| 33313635383635366232386639616230353931363032346337633639343465623935663964383031 |
| 62656530353235633833303435333934336266636336643835323031393930346262646561393561 |
| 62363339396237663838333438616538636531356162353237373264316139393334313630353638 |
| 65663365343735373165306332333030333536313263333465663738393862643633376637333633 |
| 64303735643434356237383034353438343839353466353166373337343138653665303839336532 |
| 65623536353161633939333133616665633835356333626363313430303731356439626566383335 |
| 62393438306636386135363431336538656533663264646533323566633839383438313931376262 |
| 37653130663666616531663866626162316438383365643531306336306163373731336261323463 |
| 63326661373933626664616235623566323162343763666138626238653031366364623531333038 |
| 61623236393437613461623161633766653266656633643363623161623362346637653462653136 |
| 36306561373233343836366136363363353866356663313762303066333165323464356331303962 |
| 34626163353666663831336661643331626234313232373337626134643564646161633366313534 |
| 33616632326435366462353935323032313038663961373030366564623530383361613865306333 |
| 31373434643131663132643631616331383833636262656430303064343231316166393562393262 |
| 38343539336333373738636232333266313566616633666339613933663062396462363539346233 |
| 32313431393266313936376637646263613630383231663736343133633239346435643139633039 |
| 35643365316139333830313534313330353439383631393332643333333635616563363434303832 |
| 65343233653131333464313130333334316561303132316234663530393735313464353433653563 |
| 6433363735653363366531363331316232383533623237323735 |
| """ |
| from datetime import datetime |
| from typing import Any, Dict, Iterator, List, Optional |
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| class StockService: |
| """Asset service for the stock-portfolio application.""" |
|
|
| def __init__( |
| self, |
| store: Any, |
| config: Optional[Dict[str, Any]] = None, |
| ) -> None: |
| self._store = store |
| self._cfg = config or {} |
| self._weight = self._cfg.get("weight", None) |
| logger.debug("StockService ready (store=%s)", type(store).__name__) |
|
|
| def alert_asset( |
| self, weight: Any, ticker: Any, **extra: Any |
| ) -> Dict[str, Any]: |
| """Create and persist a new Asset record.""" |
| record: Dict[str, Any] = { |
| "id": str(uuid.uuid4()), |
| "weight": weight, |
| "ticker": ticker, |
| "status": "active", |
| "created_at": datetime.utcnow().isoformat(), |
| **extra, |
| } |
| saved = self._store.put(record) |
| logger.info("alert_asset: created %s", saved["id"]) |
| return saved |
|
|
| def get_asset(self, record_id: str) -> Optional[Dict[str, Any]]: |
| """Retrieve a Asset by its *record_id*.""" |
| record = self._store.get(record_id) |
| if record is None: |
| logger.debug("get_asset: %s not found", record_id) |
| return record |
|
|
| def buy_asset( |
| self, record_id: str, **changes: Any |
| ) -> Dict[str, Any]: |
| """Apply *changes* to an existing Asset.""" |
| record = self._store.get(record_id) |
| if record is None: |
| raise KeyError(f"Asset not found: {record_id}") |
| record.update(changes) |
| record["updated_at"] = datetime.utcnow().isoformat() |
| return self._store.put(record) |
|
|
| def sell_asset(self, record_id: str) -> bool: |
| """Remove a Asset record; returns True if deleted.""" |
| if self._store.get(record_id) is None: |
| return False |
| self._store.delete(record_id) |
| logger.info("sell_asset: removed %s", record_id) |
| return True |
|
|
| def list_assets( |
| self, |
| status: Optional[str] = None, |
| limit: int = 50, |
| offset: int = 0, |
| ) -> List[Dict[str, Any]]: |
| """Return a filtered, paginated list of Asset records.""" |
| query: Dict[str, Any] = {} |
| if status: |
| query["status"] = status |
| results = self._store.find(query, limit=limit, offset=offset) |
| logger.debug("list_assets: %d results", len(results)) |
| return results |
|
|
| def iter_assets( |
| self, batch_size: int = 100 |
| ) -> Iterator[Dict[str, Any]]: |
| """Yield all Asset records in batches of *batch_size*.""" |
| offset = 0 |
| while True: |
| page = self.list_assets(limit=batch_size, offset=offset) |
| if not page: |
| break |
| yield from page |
| if len(page) < batch_size: |
| break |
| offset += batch_size |
| |