]>
git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/blob - main.py
9 __all__
= ["make_order", "get_user_market"]
11 def make_order(market
, value
, currency
, action
="acquire",
12 close_if_possible
=False, base_currency
="BTC", follow
=True,
13 compute_value
="average"):
15 Make an order on market
16 "market": The market on which to place the order
17 "value": The value in *base_currency* to acquire,
18 or in *currency* to dispose.
19 use negative for margin trade.
20 "action": "acquire" or "dispose".
21 "acquire" will buy long or sell short,
22 "dispose" will sell long or buy short.
23 "currency": The currency to acquire or dispose
24 "base_currency": The base currency. The value is expressed in that
25 currency (default: BTC)
26 "follow": Whether to follow the order once run (default: True)
27 "close_if_possible": Whether to try to close the position at the end
28 of the trade, i.e. reach exactly 0 at the end
29 (only meaningful in "dispose"). May have
30 unwanted effects if the end value of the
32 "compute_value": Compute value to place the order
34 market
.report
.log_stage("make_order_begin")
35 market
.balances
.fetch_balances(tag
="make_order_begin")
36 if action
== "acquire":
37 trade
= portfolio
.Trade(
38 portfolio
.Amount(base_currency
, 0),
39 portfolio
.Amount(base_currency
, value
),
42 amount
= portfolio
.Amount(currency
, value
)
43 trade
= portfolio
.Trade(
44 amount
.in_currency(base_currency
, market
, compute_value
=compute_value
),
45 portfolio
.Amount(base_currency
, 0),
47 market
.trades
.all
.append(trade
)
48 order
= trade
.prepare_order(
49 close_if_possible
=close_if_possible
,
50 compute_value
=compute_value
)
51 market
.report
.log_orders([order
], None, compute_value
)
52 market
.trades
.run_orders()
54 market
.follow_orders()
55 market
.balances
.fetch_balances(tag
="make_order_end")
57 market
.report
.log_stage("make_order_end_not_followed")
59 market
.report
.log_stage("make_order_end")
61 def get_user_market(config_path
, user_id
, debug
=False):
62 args
= ["--config", config_path
]
64 args
.append("--debug")
65 args
= parse_args(args
)
67 market_id
, market_config
, user_id
= list(fetch_markets(str(user_id
)))[0]
68 return market
.Market
.from_config(market_config
, args
, user_id
=user_id
)
70 def fetch_markets(user
):
71 cursor
= dbs
.psql
.cursor()
74 cursor
.execute("SELECT id,config,user_id FROM market_configs")
76 cursor
.execute("SELECT id,config,user_id FROM market_configs WHERE user_id = %s", user
)
81 def parse_config(args
):
82 if args
.db_host
is not None:
83 dbs
.connect_psql(args
)
85 if args
.redis_host
is not None:
86 dbs
.connect_redis(args
)
88 report_path
= args
.report_path
90 if report_path
is not None and not \
91 os
.path
.exists(report_path
):
92 os
.makedirs(report_path
)
95 parser
= configargparse
.ArgumentParser(
96 description
="Run the trade bot.")
98 parser
.add_argument("-c", "--config",
100 required
=False, is_config_file
=True,
101 help="Config file to load (default: config.ini)")
102 parser
.add_argument("--before",
103 default
=False, action
='store_const', const
=True,
104 help="Run the steps before the cryptoportfolio update")
105 parser
.add_argument("--after",
106 default
=False, action
='store_const', const
=True,
107 help="Run the steps after the cryptoportfolio update")
108 parser
.add_argument("--quiet",
109 default
=False, action
='store_const', const
=True,
110 help="Don't print messages")
111 parser
.add_argument("--debug",
112 default
=False, action
='store_const', const
=True,
113 help="Run in debug mode")
114 parser
.add_argument("--user",
115 default
=None, required
=False, help="Only run for that user")
116 parser
.add_argument("--action",
118 help="Do a different action than trading (add several times to chain)")
119 parser
.add_argument("--parallel", action
='store_true', default
=True, dest
="parallel")
120 parser
.add_argument("--no-parallel", action
='store_false', dest
="parallel")
121 parser
.add_argument("--report-db", action
='store_true', default
=True, dest
="report_db",
122 help="Store report to database (default)")
123 parser
.add_argument("--no-report-db", action
='store_false', dest
="report_db",
124 help="Don't store report to database")
125 parser
.add_argument("--report-redis", action
='store_true', default
=False, dest
="report_redis",
126 help="Store report to redis")
127 parser
.add_argument("--no-report-redis", action
='store_false', dest
="report_redis",
128 help="Don't store report to redis (default)")
129 parser
.add_argument("--report-path", required
=False,
130 help="Where to store the reports (default: absent, don't store)")
131 parser
.add_argument("--no-report-path", action
='store_const', dest
='report_path', const
=None,
132 help="Don't store the report to file (default)")
133 parser
.add_argument("--db-host", default
="localhost",
134 help="Host access to database (default: localhost)")
135 parser
.add_argument("--db-port", default
=5432,
136 help="Port access to database (default: 5432)")
137 parser
.add_argument("--db-user", default
="cryptoportfolio",
138 help="User access to database (default: cryptoportfolio)")
139 parser
.add_argument("--db-password", default
="cryptoportfolio",
140 help="Password access to database (default: cryptoportfolio)")
141 parser
.add_argument("--db-database", default
="cryptoportfolio",
142 help="Database access to database (default: cryptoportfolio)")
143 parser
.add_argument("--redis-host", default
="localhost",
144 help="Host access to database (default: localhost). Use path for socket")
145 parser
.add_argument("--redis-port", default
=6379,
146 help="Port access to redis (default: 6379)")
147 parser
.add_argument("--redis-database", default
=0,
148 help="Redis database to use (default: 0)")
150 parsed
= parser
.parse_args(argv
)
151 if parsed
.action
is None:
152 parsed
.action
= ["sell_all"]
155 def process(market_config
, market_id
, user_id
, args
):
158 .from_config(market_config
, args
, market_id
=market_id
,
160 .process(args
.action
, before
=args
.before
, after
=args
.after
)
161 except Exception as e
:
162 print("{}: {}".format(e
.__class
__.__name
__, e
))
165 args
= parse_args(argv
)
169 market
.Portfolio
.report
.set_verbose(not args
.quiet
)
173 market
.Portfolio
.start_worker()
177 thread
= threading
.Thread(target
=process
, args
=args
)
179 threads
.append(thread
)
183 for market_id
, market_config
, user_id
in fetch_markets(args
.user
):
184 process_(market_config
, market_id
, user_id
, args
)
187 for thread
in threads
:
189 market
.Portfolio
.stop_worker()
191 if __name__
== '__main__': # pragma: no cover