]>
git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/blob - main.py
1 from datetime
import datetime
11 __all__
= ["make_order", "get_user_market"]
13 def make_order(market
, value
, currency
, action
="acquire",
14 close_if_possible
=False, base_currency
="BTC", follow
=True,
15 compute_value
="average"):
17 Make an order on market
18 "market": The market on which to place the order
19 "value": The value in *base_currency* to acquire,
20 or in *currency* to dispose.
21 use negative for margin trade.
22 "action": "acquire" or "dispose".
23 "acquire" will buy long or sell short,
24 "dispose" will sell long or buy short.
25 "currency": The currency to acquire or dispose
26 "base_currency": The base currency. The value is expressed in that
27 currency (default: BTC)
28 "follow": Whether to follow the order once run (default: True)
29 "close_if_possible": Whether to try to close the position at the end
30 of the trade, i.e. reach exactly 0 at the end
31 (only meaningful in "dispose"). May have
32 unwanted effects if the end value of the
34 "compute_value": Compute value to place the order
36 market
.report
.log_stage("make_order_begin")
37 market
.balances
.fetch_balances(tag
="make_order_begin")
38 if action
== "acquire":
39 trade
= portfolio
.Trade(
40 portfolio
.Amount(base_currency
, 0),
41 portfolio
.Amount(base_currency
, value
),
44 amount
= portfolio
.Amount(currency
, value
)
45 trade
= portfolio
.Trade(
46 amount
.in_currency(base_currency
, market
, compute_value
=compute_value
),
47 portfolio
.Amount(base_currency
, 0),
49 market
.trades
.all
.append(trade
)
50 order
= trade
.prepare_order(
51 close_if_possible
=close_if_possible
,
52 compute_value
=compute_value
)
53 market
.report
.log_orders([order
], None, compute_value
)
54 market
.trades
.run_orders()
56 market
.follow_orders()
57 market
.balances
.fetch_balances(tag
="make_order_end")
59 market
.report
.log_stage("make_order_end_not_followed")
61 market
.report
.log_stage("make_order_end")
63 def get_user_market(config_path
, user_id
, debug
=False):
64 pg_config
, report_path
= parse_config(config_path
)
65 market_config
= list(fetch_markets(pg_config
, str(user_id
)))[0][0]
66 return market
.Market
.from_config(market_config
, debug
=debug
)
68 def fetch_markets(pg_config
, user
):
69 connection
= psycopg2
.connect(**pg_config
)
70 cursor
= connection
.cursor()
73 cursor
.execute("SELECT config,user_id FROM market_configs")
75 cursor
.execute("SELECT config,user_id FROM market_configs WHERE user_id = %s", user
)
80 def parse_config(config_file
):
81 config
= configparser
.ConfigParser()
82 config
.read(config_file
)
84 if "postgresql" not in config
:
85 print("no configuration for postgresql in config file")
88 if "app" in config
and "report_path" in config
["app"]:
89 report_path
= config
["app"]["report_path"]
91 if not os
.path
.exists(report_path
):
92 os
.makedirs(report_path
)
96 return [config
["postgresql"], report_path
]
99 parser
= argparse
.ArgumentParser(
100 description
="Run the trade bot")
102 parser
.add_argument("-c", "--config",
103 default
="config.ini",
105 help="Config file to load (default: config.ini)")
106 parser
.add_argument("--before",
107 default
=False, action
='store_const', const
=True,
108 help="Run the steps before the cryptoportfolio update")
109 parser
.add_argument("--after",
110 default
=False, action
='store_const', const
=True,
111 help="Run the steps after the cryptoportfolio update")
112 parser
.add_argument("--debug",
113 default
=False, action
='store_const', const
=True,
114 help="Run in debug mode")
115 parser
.add_argument("--user",
116 default
=None, required
=False, help="Only run for that user")
117 parser
.add_argument("--action",
119 help="Do a different action than trading (add several times to chain)")
121 args
= parser
.parse_args(argv
)
123 if not os
.path
.exists(args
.config
):
124 print("no config file found, exiting")
129 def process(market_config
, user_id
, report_path
, args
):
132 .from_config(market_config
, debug
=args
.debug
, user_id
=user_id
, report_path
=report_path
)\
133 .process(args
.action
, before
=args
.before
, after
=args
.after
)
134 except Exception as e
:
135 print("{}: {}".format(e
.__class
__.__name
__, e
))
138 args
= parse_args(argv
)
140 pg_config
, report_path
= parse_config(args
.config
)
142 for market_config
, user_id
in fetch_markets(pg_config
, args
.user
):
143 process(market_config
, user_id
, report_path
, args
)
145 if __name__
== '__main__': # pragma: no cover