]>
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
, options
= list(fetch_markets(str(user_id
)))[0]
68 return market
.Market
.from_config(market_config
, args
, user_id
=user_id
, options
=options
)
70 def fetch_markets(user
):
71 cursor
= dbs
.psql
.cursor()
74 cursor
.execute("SELECT id,config,user_id,portfolio_profile FROM market_configs_augmented WHERE status='enabled'")
76 cursor
.execute("SELECT id,config,user_id,portfolio_profile FROM market_configs_augmented WHERE status='enabled' AND user_id = %s", [user
])
80 "liquidity": parse_liquidity(row
[3])
82 yield row
[0:3] + (options
,)
84 def parse_liquidity(value
):
85 if value
== "high-liquidity":
87 elif value
== "medium-liquidity":
92 def parse_config(args
):
93 if args
.db_host
is not None:
94 dbs
.connect_psql(args
)
96 if args
.redis_host
is not None:
97 dbs
.connect_redis(args
)
99 report_path
= args
.report_path
101 if report_path
is not None and not \
102 os
.path
.exists(report_path
):
103 os
.makedirs(report_path
)
105 def parse_args(argv
):
106 parser
= configargparse
.ArgumentParser(
107 description
="Run the trade bot.")
109 parser
.add_argument("-c", "--config",
110 default
="config.ini",
111 required
=False, is_config_file
=True,
112 help="Config file to load (default: config.ini)")
113 parser
.add_argument("--before",
114 default
=False, action
='store_const', const
=True,
115 help="Run the steps before the cryptoportfolio update")
116 parser
.add_argument("--after",
117 default
=False, action
='store_const', const
=True,
118 help="Run the steps after the cryptoportfolio update")
119 parser
.add_argument("--quiet",
120 default
=False, action
='store_const', const
=True,
121 help="Don't print messages")
122 parser
.add_argument("--debug",
123 default
=False, action
='store_const', const
=True,
124 help="Run in debug mode")
125 parser
.add_argument("--user",
126 default
=None, required
=False, help="Only run for that user")
127 parser
.add_argument("--action",
129 help="Do a different action than trading (add several times to chain)")
130 parser
.add_argument("--parallel", action
='store_true', default
=True, dest
="parallel")
131 parser
.add_argument("--no-parallel", action
='store_false', dest
="parallel")
132 parser
.add_argument("--report-db", action
='store_true', default
=True, dest
="report_db",
133 help="Store report to database (default)")
134 parser
.add_argument("--no-report-db", action
='store_false', dest
="report_db",
135 help="Don't store report to database")
136 parser
.add_argument("--report-redis", action
='store_true', default
=False, dest
="report_redis",
137 help="Store report to redis")
138 parser
.add_argument("--no-report-redis", action
='store_false', dest
="report_redis",
139 help="Don't store report to redis (default)")
140 parser
.add_argument("--report-path", required
=False,
141 help="Where to store the reports (default: absent, don't store)")
142 parser
.add_argument("--no-report-path", action
='store_const', dest
='report_path', const
=None,
143 help="Don't store the report to file (default)")
144 parser
.add_argument("--db-host", default
="localhost",
145 help="Host access to database (default: localhost)")
146 parser
.add_argument("--db-port", default
=5432,
147 help="Port access to database (default: 5432)")
148 parser
.add_argument("--db-user", default
="cryptoportfolio",
149 help="User access to database (default: cryptoportfolio)")
150 parser
.add_argument("--db-password", default
="cryptoportfolio",
151 help="Password access to database (default: cryptoportfolio)")
152 parser
.add_argument("--db-database", default
="cryptoportfolio",
153 help="Database access to database (default: cryptoportfolio)")
154 parser
.add_argument("--redis-host", default
="localhost",
155 help="Host access to database (default: localhost). Use path for socket")
156 parser
.add_argument("--redis-port", default
=6379,
157 help="Port access to redis (default: 6379)")
158 parser
.add_argument("--redis-database", default
=0,
159 help="Redis database to use (default: 0)")
161 parsed
= parser
.parse_args(argv
)
162 if parsed
.action
is None:
163 parsed
.action
= ["sell_all"]
166 def process(market_config
, market_id
, user_id
, args
, options
):
169 .from_config(market_config
, args
, market_id
=market_id
,
170 user_id
=user_id
, options
=options
)\
171 .process(args
.action
, before
=args
.before
, after
=args
.after
)
172 except Exception as e
:
173 print("{}: {}".format(e
.__class
__.__name
__, e
))
176 args
= parse_args(argv
)
180 market
.Portfolio
.report
.set_verbose(not args
.quiet
)
184 market
.Portfolio
.start_worker()
188 thread
= threading
.Thread(target
=process
, args
=args
)
190 threads
.append(thread
)
194 for market_id
, market_config
, user_id
, options
in fetch_markets(args
.user
):
195 process_(market_config
, market_id
, user_id
, args
, options
)
198 for thread
in threads
:
200 market
.Portfolio
.stop_worker()
202 if __name__
== '__main__': # pragma: no cover