728x90
참고 : https://docs.upbit.com/changelog/open-api-%EB%B3%80%EA%B2%BD%EC%82%AC%ED%95%AD-%EC%95%88%EB%82%B4
안녕하세요 블로그 주인입니다.
2022년 03월 01일부터 API변경사항이 있습니다.
"업비트 자동매매 만들기"의 소스에서
주문하기, 취소주문, 주문수정 등(=Post)을 서버로 데이터를 보낼경우
기존에는 key1=value1&key2=value2.... (=Query String)이런 형식으로 서버로 데이터를 보냈지만,
앞으로는 Json Body로만 받겠다는 의미입니다.
아래의 수정사항을 간단하게 설명하면,
Post함수를 만든 후, 인증 토큰은 Query String형태로 만들고,
Dictionary<string, string> 형태로 받은 데이터를 JsonConvert.SerializeObject( object )함수로
Json형태로 바꿔주어
request.AddJsonBody로 추가해줍니다.
- 수정사항1
UpbitAPI - Param.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt;
using RestSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace upbit.UpbitAPI {
public class Param {
private string upbitAccessKey;
private string upbitSecretKey;
private DateTime dt_1970_01_01; //timestamp를 계산하기 위한 변수
private const string baseUrl = "https://api.upbit.com";
public Param(string upbitAccessKey, string upbitSecretKey) {
//APIClass에서 받은 키를 입력
this.upbitAccessKey = upbitAccessKey;
this.upbitSecretKey = upbitSecretKey;
this.dt_1970_01_01 = new DateTime(1970, 1, 1);
}
/*------------------------------ 수정부분 시작 ------------------------------*/
public string Post(string path, Dictionary<string, string> parameters, Method method) {
// POST, DELETE, UPDATE 방식을 포함하는듯?
StringBuilder queryStringSb = GetQueryString(parameters);
var tokenSb = JWT_param(queryStringSb.ToString()); // 입력받은 변수를 JWT토큰으로 변환
var token = tokenSb.ToString();
var client = new RestClient(baseUrl);
var request = new RestRequest(path, method);
// JsonConvert.SerializeObject(parameters); // dictionary to Json
request.AddJsonBody( JsonConvert.SerializeObject(parameters) ); // add Json to body
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", token);
var response = client.Execute(request);
try {
if (response.IsSuccessful) {
return response.Content;
}
else {
return null;
}
}
catch {
return null;
}
}
/*------------------------------ 수정부분 끝 ------------------------------*/
public string Get(string path, Dictionary<string, string> parameters, Method method) {
StringBuilder queryStringSb = GetQueryString(parameters);
var tokenSb = JWT_param(queryStringSb.ToString()); // 입력받은 변수를 JWT토큰으로 변환
var token = tokenSb.ToString();
queryStringSb.Insert(0, "?"); // 링크에 ?를 붙임으로 파라미터를 사용한다는 의미
queryStringSb.Insert(0, path);
// 여기까지오면 queryString는
// '/path?key1=value1&key2=value2 ....' 이러한 형태가 된다. 이것을 RestRequest에 넣어주면 된다.
var client = new RestClient(baseUrl); // RestSharp 클라이언트 생성
var request = new RestRequest(queryStringSb.ToString(), method);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", token);
queryStringSb.Clear(); queryStringSb = null;
tokenSb.Clear(); tokenSb = null;
parameters.Clear(); parameters = null;
var response = client.Execute(request);
try {
if (response.IsSuccessful) {
return response.Content;
}
else {
return null;
}
}
catch {
return null;
}
}
public StringBuilder GetQueryString(Dictionary<string, string> parameters) {
// Dictionary 형태로 받은 key = value 형태를
// ?key1=value1&key2=value2 ... 형태로 만들어줌
StringBuilder builder = new StringBuilder();
foreach (KeyValuePair<string, string> pair in parameters) {
builder.Append(pair.Key).Append("=").Append(pair.Value).Append("&");
}
if (builder.Length > 0) {
builder.Length = builder.Length - 1; // 마지막 &를 제거하기 위함.
}
return builder;
}
public StringBuilder JWT_param(string queryString) {
SHA512 sha512 = SHA512.Create();
byte[] queryHashByteArray = sha512.ComputeHash(Encoding.UTF8.GetBytes(queryString));
string queryHash = BitConverter.ToString(queryHashByteArray).Replace("-", "").ToLower();
TimeSpan diff = DateTime.Now - dt_1970_01_01;
var nonce = Convert.ToInt64(diff.TotalMilliseconds);
var payload = new JwtPayload
{
{ "access_key", this.upbitAccessKey },
{ "nonce", nonce },
{ "query_hash", queryHash },
{ "query_hash_alg", "SHA512" }
};
byte[] keyBytes = Encoding.Default.GetBytes(this.upbitSecretKey);
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyBytes);
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "HS256");
var header = new JwtHeader(credentials);
var secToken = new JwtSecurityToken(header, payload);
var jwtToken = new JwtSecurityTokenHandler().WriteToken(secToken);
StringBuilder returnStr = new StringBuilder();
returnStr.Append("Bearer "); // 띄어쓰기 한칸 있어야함 주의!
returnStr.Append(jwtToken);
return returnStr;
}
}
}
- 수정사항2
UpbitAPI - APIClass.cs
주문 관련된 함수에서 Param.Get → Param.Post로 변경
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using upbit.UpbitAPI.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace upbit.UpbitAPI {
public class APIClass {
private Param param;
private NoParam noparam;
public APIClass(string upbitAccessKey, string upbitSecretKey) {
param = new Param(upbitAccessKey, upbitSecretKey);
noparam = new NoParam(upbitAccessKey, upbitSecretKey);
}
/*--------------------- EXCHANGE API ---------------------*/
public List<Account> GetAccount() {
// 자산 - 전체 계좌 조회
var data = noparam.Get("/v1/accounts", RestSharp.Method.GET);
if (data != null ) {
return JsonConvert.DeserializeObject<List<Account>>(data);
}
else {
return null;
}
}
public OrderChance GetOrderChance(string market) {
// 주문 - 주문 가능 정보
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add( "market", market );
var data = param.Get("/v1/orders/chance", parameters, RestSharp.Method.GET);
if ( data != null ) {
return JsonConvert.DeserializeObject<OrderChance>(data);
}
else {
return null;
}
}
public Order GetOrder(string uuid) {
// 주문 - 개별 주문 조회
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("uuid", uuid);
var data = param.Get("/v1/order", parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<Order>(data);
}
else {
return null;
}
}
public CancelOrder CancelOrder(string uuid) {
// 주문 - 주문 취소 접수
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("uuid", uuid);
var data = param.Post("/v1/order", parameters, RestSharp.Method.DELETE);
if ( data != null ) {
return JsonConvert.DeserializeObject<CancelOrder>(data);
}
else {
return null;
}
}
public MakeOrder MakeOrderLimit(string market, OrderSide orderSide, double volume, double price ) {
// 주문 - 주문하기 - 지정가 매수&매도
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("side", orderSide.ToString());
parameters.Add("volume", volume.ToString());
parameters.Add("price", price.ToString());
parameters.Add("ord_type", "limit");
var data = param.Post("/v1/orders", parameters, RestSharp.Method.POST);
if ( data != null ) {
return JsonConvert.DeserializeObject<MakeOrder>(data);
}
else {
return null;
}
}
public MakeOrderMarketBuy MakeOrderMarketBuy(string market, double price ) {
// 주문 - 주문하기 - 시장가매수
/* 주문 가격. (지정가, 시장가 매수 시 필수)
ex) KRW-BTC 마켓에서 1BTC당 1,000 KRW로 거래할 경우, 값은 1000 이 된다.
ex) KRW-BTC 마켓에서 1BTC당 매도 1호가가 500 KRW 인 경우,
시장가 매수 시 값을 1000으로 세팅하면 2BTC가 매수된다.
(수수료가 존재하거나 매도 1호가의 수량에 따라 상이할 수 있음)
--> 결론 : price는 원화가치인듯 */
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("side", OrderSide.bid.ToString());
parameters.Add("price", price.ToString());
parameters.Add("ord_type", "price");
var data = param.Post("/v1/orders", parameters, RestSharp.Method.POST);
if (data != null) {
return JsonConvert.DeserializeObject<MakeOrderMarketBuy>(data);
}
else {
return null;
}
}
public MakeOrderMarketSell MakeOrderMarketSell(string market, double volume ) {
// 주문 - 주문하기 - 시장가매도
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("side", OrderSide.ask.ToString() );
parameters.Add("volume", volume.ToString());
parameters.Add("ord_type", "market");
var data = param.Post("/v1/orders", parameters, RestSharp.Method.POST);
if (data != null) {
return JsonConvert.DeserializeObject<MakeOrderMarketSell>(data);
}
else {
return null;
}
}
/*--------------------- QUOTATION API ---------------------*/
public List<MarketAll> GetMarketAll() {
// 시세 종목 조회 - 마켓 코드 조회
var data = noparam.Get("/v1/market/all", RestSharp.Method.GET);
return JsonConvert.DeserializeObject<List<MarketAll>>(data);
}
public List<CandleMinute> GetCandleMinutes( string market, MinuteUnit unit, DateTime to=default(DateTime) , int count = 1 ) {
// 시세 캔들 조회 - 분(Minute) 캔들
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("to", to.ToString("yyyy-MM-dd HH:mm:ss"));
parameters.Add("count", count.ToString());
var data = param.Get(String.Join("", "/v1/candles/minutes/", (int)unit), parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<List<CandleMinute>>(data);
}
else {
return null;
}
}
public List<CandleDay> GetCandleDays(string market, DateTime to = default(DateTime), int count = 1) {
// 시세 캔들 조회 - 일(Day) 캔들
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("to", to.ToString("yyyy-MM-dd HH:mm:ss"));
parameters.Add("count", count.ToString());
var data = param.Get("/v1/candles/days", parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<List<CandleDay>>(data);
}
else {
return null;
}
}
public List<CandleWeek> GetCandleWeeks(string market, DateTime to = default(DateTime), int count = 1) {
// 시세 캔들 조회 - 주(Week) 캔들
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("to", to.ToString("yyyy-MM-dd HH:mm:ss"));
parameters.Add("count", count.ToString());
var data = param.Get("/v1/candles/weeks", parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<List<CandleWeek>>(data);
}
else {
return null;
}
}
public List<CandleMonth> GetCandleMonths(string market, DateTime to = default(DateTime), int count = 1) {
// 시세 캔들 조회 - 월(Month) 캔들
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("market", market);
parameters.Add("to", to.ToString("yyyy-MM-dd HH:mm:ss"));
parameters.Add("count", count.ToString());
var data = param.Get("/v1/candles/months", parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<List<CandleMonth>>(data);
}
else {
return null;
}
}
public List<Ticker> GetTicker(string markets) {
// 시세 Ticker조회 - 현재가정보
// market을 콤마로 구분하여 입력한다.
// ex) "KRW-BTC, KRW-ETH, ....."
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("markets", markets);
var data = param.Get("/v1/ticker", parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<List<Ticker>>(data);
}
else {
return null;
}
}
public List<OrderBook> GetOrderBook(string markets) {
// 시세 호가 정보 조회 - 호가 정보 조회
// market을 콤마로 구분하여 입력한다.
// ex) "KRW-BTC, KRW-ETH, ....."
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("markets", markets);
var data = param.Get("/v1/orderbook", parameters, RestSharp.Method.GET);
if (data != null) {
return JsonConvert.DeserializeObject<List<OrderBook>>(data);
}
else {
return null;
}
}
public enum OrderSide {
bid, // 매수
ask // 매도
}
public enum MinuteUnit {
_1 = 1,
_3 = 3,
_5 = 5,
_10 = 10,
_15 = 15,
_30 = 30,
_60 = 60,
_240 = 240
}
}
}
'업비트 자동매매 만들기' 카테고리의 다른 글
[#7-4][업비트 자동매매 C# winform][수정사항] (20) | 2022.03.31 |
---|---|
[#7-3][업비트 자동매매 C# winform][종가베팅_매도] (1) | 2022.03.31 |
[#7-2][업비트 자동매매 C# winform][종가베팅_매수] (4) | 2022.02.09 |
[#7-1][업비트 자동매매 C# winform][종가베팅_함수작성] (0) | 2022.01.24 |
[#7-0][업비트 자동매매 C# winform][종가 베팅] (0) | 2022.01.21 |
댓글