market-maker icon indicating copy to clipboard operation
market-maker copied to clipboard

Added capability of retrieving price info from Taptools

Open ajuggler opened this issue 11 months ago • 9 comments

Most relevant new function is getTaptoolsPrice defined in 'Prices.hs' .

ToDo: Add code to stop bot if price discrepancy is beyond some threshold.

ajuggler avatar Mar 21 '24 06:03 ajuggler

Since Taptools aggregates the price provided by MinSwap (and provided by Maestro), it seems desirable to have the capability of fine-tunning the weights of each Prices Provider. Last commit enables that.

ajuggler avatar Apr 13 '24 20:04 ajuggler

With last commit, buildPP now checks that

  • Length of list of weights coincides with number of prices providers;
  • "Threshold2" is not smaller than "Threshold1".

ajuggler avatar Apr 13 '24 20:04 ajuggler

Successfully tested:

  • Working Taptools price feed.
  • Config file is backwards compatible.

As well as these scenarios:

  • Maestro price is unavailable (warns but MMBot continues)
  • Taptools price is unavailable (warns but MMBot continues)
  • Both Maestro and Taptools are unavailable (warns and closes all orders)
  • Price mismatch lower than given threshold (continues normally; since price average changed, MMBot updates orders accordingly)
  • Price mismatch larger than given threshold (closes all orders)

Note: as mechanism to flag changes while MMBot is running, the following files can be updated:

  • offset_price.txt (initial content: 0)
  • maestro_available.txt (initial content: True)
  • taptools_available.txt (initial content: True)

ajuggler avatar Apr 19 '24 07:04 ajuggler

State in exectueStrategy (MakerBot.hs) is:

data MBFret = MBReady | MBSpooked1
                        { mbsRelax1 ∷ !Int
                        , mbsWorse1 ∷ !Int
                        }
                      | MBSpooked2
                        { mbsRelax2 ∷ !Int }

Counters' role are as follows:

  • mbsRelax1: relaxation progress after prices providers return to agreement; new mismatch resets this counter.
  • mbsWorse1: if its max value is reached, state switches to "MBSpooked2".
  • mbsRelax2: same as mbsRelax1 but in the context of "outrageous" price mismatch.

ajuggler avatar Apr 22 '24 01:04 ajuggler

As per convention in 'sample-preprod-maker-bot-config-gens-v2.yaml', flag files are:

  • 'offset_price.txt': content of this file is artificially added to Maestro's price.
  • 'maestro_available.txt': if its content is False, Maestro is artificially unavailable.
  • 'taptools_available.txt': it its content is False, Taptools is artificially unavailable.

If flag files are not present, default values (zero, True and True, respectively) are assumed.

ajuggler avatar Apr 22 '24 02:04 ajuggler

To be on the safe side, I included secrets/ in .dockerignore. Was this necessary?

ajuggler avatar Apr 25 '24 00:04 ajuggler

Latest changes:

  • I removed all code duplication in testing suite.
  • Added a third prices provider, so now PricesProviderCfg is:
data PricesProviderCfg =
    MaestroPPC MaestroConfig
  | TaptoolsPPC TaptoolsConfig
  | MockPPC MockConfig

Executing cabal test resulted in:

OK (733.48s)

All 1 tests passed (733.51s)
Test suite pproviders-status-sequence: PASS
Test suite logged to:
/Users/antonio/code/haskell/geniusyield/market-maker/dist-newstyle/build/x86_64-osx/ghc-9.2.8/geniusyield-market-maker-0.3.0/t/pproviders-status-sequence/test/geniusyield-market-maker-0.3.0-pproviders-status-sequence.log
1 of 1 test suites (1 of 1 test cases) passed.

ajuggler avatar May 05 '24 17:05 ajuggler

Latest commit addresses the following issues:

  • If Maestro failed to provide price, execution would stop with an exception instead of relying on the other prices provider(s).
  • The warning log message stating that a prices provider failed was not indicating which one.
  • There was an inconsistency in where in the code the "prices provider fail" log message was being triggered.

With latest commit, prices provider failure consists of:

  1. Warning that "Some prices provider(s) failed: " and a list of those that failed.
  2. Logging the exceptions thrown by each failing prices provider.

Function logPricesProviderFail ∷ GYProviders → PriceIndicator → IO (), exported by module Strategies, implements the above.

To elaborate, logging of a prices provider failure can occur if some, but not all, prices providers fail:

  • While executing the trading strategy, or
  • While on standby (in "spooked mode") waiting to confirm that all prices providers are again in agreement.

ajuggler avatar May 06 '24 02:05 ajuggler

I believe this PR is ready to be merged into main, and that the following outstanding issues can be worked out while MMBot is being tested on Preprod, as a separate PR.

Outstanding issues:

  • [ ] Log each client's exception in the unlikely case that all prices providers fail. (Currently only a warning message announcing all prices providers failed is logged.)
  • [x] Use CURL to query taptools prices (in order to be able to use https).
  • [x] Consider removing parameter pccAfterExitRelaxAim1.
  • [x] Add security measure to make sure that secret taptools key is not logged in case of taptools failure.
  • [ ] Improve testing suite by adding appropriate exceptions in the validation logic.

ajuggler avatar May 06 '24 05:05 ajuggler

Experimentation shows that, with original definition of taptoolsManager,

taptoolsManager :: Confidential Text -> IO Manager
taptoolsManager apiKey = newManager $ tlsManagerSettings { managerModifyRequest = withHeaders }
  where
    Confidential apiKey' = apiKey

    withHeaders :: Request -> IO Request
    withHeaders req = do
      return $ req { requestHeaders = ("x-api-key", encodeUtf8 apiKey') :
                                      filter (("x-api-key" /=) . fst) (requestHeaders req)
                   }

API key is automatically concealed in error logs.

ajuggler avatar May 13 '24 01:05 ajuggler