728x90

SW Expert Academy는 알고리즘테스트(코딩테스트)를 준비하기에 정말 좋은사이트 인것같다.

프로그래머스도 공부하기 좋지만 SW Expert 아카데미는 삼성에서 직접 운영중인 웹사이트이며

자신의 실력을 테스트하는 코딩테스트를 통해 학습 로드맵을 제공해주는게 정말 좋은사이트이다.

 

 

https://swexpertacademy.com/main/main.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

CodeProblem Solving매주 제공되는 난이도별 SW 연습문제에 도전하세요. 

LearnIntensive Study프로그래밍 역량강화를 위한 필수 이론 및 지식을 개인 역량에 따라 스스로 학습할 수 있도록 다양한 유형의 학습 컨텐츠를 제공합니다.

TalkSocial Learning함께 코드를 리뷰하고 토론하세요. 서로 소통하며 협업하는 가운데 모두의 실력이 향상됩니다.

 레벨 테스트를 통하여 개인 역량에 맞는 컨텐츠를 추천 받아 학습할 수 있습니다.

 

또한 알고리즘을 시각적으로 확인할수있다는 큰 장점이있다!

728x90

'경험' 카테고리의 다른 글

42seoul - la piscine 후기 (42서울 라피신 후기 )  (4) 2020.11.24
728x90

 

퀵정렬(Quick sort)

 

퀵정렬은 대표적인 분할정복 알고리즘중에 하나이다.

분할정렬이란 하나의 특정한 값을 기준으로 양 쪽을 나눠서 정렬하는 것이다.

 

퀵정렬은 운이좋으면 아주빠르게 처리되기때문에 붙은이름이며

평균적으로 시간복잡도가 O(N * logN) 입니다.

 

 

 

3 7 8 1 5 9 6 10 2 4을 오름차순으로 정렬하시오

 

▶퀵 정렬

풀기 어려운 큰 문제를 작은 문제로 나누어 푸는 분할 정복을 이용합니다. 방법은 아래와 같습니다.

1. 입력 받은 리스트에서 기준이 되는 값인 pivot을 설정한다.

2. pivot을 기준으로 pivot보다 작은 값은 왼쪽에, 큰 값은 오른쪽에 옮겨진다.

3. 왼쪽, 오른쪽 리스트의 크기가 1이 될 때까지, 1,2번을 반복한다.

 

이러한 정렬을 퀵소트를 통해 정렬시킬수 있습니다.

 

퀵정렬은 피봇이라는 기준값을 사용하는데 보통 첫번째 값을 피봇으로 사용합니다. 위에 예시를 봤을때 

 

 

3 7 8 1 5 9 6 10 2 4

1. 맨앞에 있는값(3)을 피봇으로 설정합니다

왼쪽부터(7부터) 피봇값(3)보다 큰값을 찾습니다.

오른쪽(4)부터 피봇값(3)보다 작은값을 찾습니다.

큰값은 7, 작은값은 2가 될것이며

둘의 위치를 바꿔 줍니다.

 

3 2 8 1 5 9 6 10 7 4

2. 또다시 피봇은 3인채로 똑같이 왼쪽부터 큰값을, 오른쪽부터 작은값을 찾습니다.

큰값은 8 작은값은 1이 될것입니다.둘의 위치를 바꿔줍니다.

 

3 2 1 8 5 9 6 10 7 4

 

 

3. 또 피봇은3인채로 왼쪽부터 피봇보다 큰값을, 오른쪽부터 피봇보다 작은값을 찾습니다.

큰값 8 , 작은값 1이 발견될텐데 이때 작은값의 인덱스가 큰값의 인덱스보다 작습니다.

따라서 피봇값과 작은값은 자리를 바꿔줍니다. 이를 엇갈렸다고 표현하겠습니다.

엇갈렸을때 피봇값과 작은값의 자리를 바꾸는데 그 바꾼후 피봇값(3)은 자리가 고정이 됩니다.

왜냐하면 3의 왼쪽에는 자기보다 작은값만존재하고 , 오른쪽에는 자기자신보다 큰값만 존재하기 떄문

 

2 3 8 5 9 6 10 7 4

4. 피봇값3을 기준으로 배열은 반으로 쪼개서 방금까지 했던 작업들을 각각 합니다.즉 왼쪽(1 2 ) 부터 생각하면

 

2

4-1(왼쪽) 1을 피봇으로 설정하고 왼쪽부터 피봇값(1)보다 큰값을 오른쪽부터 피봇값(1)보다 작은값을 찾습니다.

큰값은 2, 작은값은 1(자기자신) 이떄 작은값의 인덱스가 큰값의 인덱스보다 작으므로 마찬가지로 작은값과 피봇의 인덱스를 바꿔줍니다(즉 작은값1, 피봇값1 이므로 변화는없습니다)  엇갈렸으므로 1은 자리가 고정이되고

1의 왼쪽값들을 퀵소트해주는데 왼쪽값이 없으므로 생략,

1의 오른쪽값들을 퀵소트해주는데 값이 2 하나이므로 2도 자리가 고정이되며

1, 2 3 은 자리가 확정이됩니다.

이제 아까3의 오른쪽값들을 퀵소트해줍니다.

 

8 5 9 6 10 7 4

 

4-2(오른쪽)  피봇을 첫번째값(8)로 설정하고 왼쪽부터 피봇값(8)보다 큰값을 오른쪽부터 피봇값(8)보다 작은값을 찾습니다.

큰값9, 작은값 4가 정해질것이며 둘의 자리를 바꿉니다.

8 5 4 6 10 7 9

 

4-3 또 피봇값(8)보다 왼쪽부터 큰값을, 오른쪽부터 작은값을 찾습니다. 

작큰값은 10, 작은값은 7 둘의 자리를 바꿉니다.

 

8 5 4 6 7 10 9

4-4 피봇값보다 왼쪽부터 큰값을 오른쪽부터 작은값을 찾습니다.

큰값은 10이며 작은값은 7 

이떄 작은값의 인덱스가 큰값의 인덱스보다 작으므로 엇갈렸다고 표현할수있습니다.작은값과 피봇과 자리를 바꿉니다.

 

 

7 5 4 6 8 10 9

4-5 8은 자리가 고정이 되었고 이제 8을 기준으로 왼쪽 7 5 4 6을 퀵소트해주고 

8의 오른쪽 10 9를 퀵소트 해줍니다.

 

 

5 4 6 

맨앞의 값을 피봇으로 정하고 왼쪽부터 큰값을 오른쪽부터 작은값을 찾습니다.

이떄 작은값6과 큰값x

이떄도 엇갈렸다고 표현하는데 피봇과 작은값의 자리를 바꿔주고 7은 자리가 고정이되며바꾼 피봇값의 자리를기준으로 왼쪽 오른쪽을 나눠서 퀵소트를 진행해줍니다.

5 4 6 7

 

 

 

5 4 6 

 

5를 피봇으로 왼쪽부터 큰값 오른쪽부터 작은값을 찾습니다.

큰값6 작은값 4엇갈렸으므로 작은값과 피봇값의 자리를바꾸고 바꾼 피봇값은 고정이되며 또 왼쪽 오른쪽을 나눠서 퀵소트를 진행

 

 4 5 6 

5는 고정된값이며 왼쪽값이 하나이므로 4도 고정

5의 오른쪽도 정렬할 값이 하나이므로 6도 고정

 

 

7 5 4 6 8 10 9 여기서 왼쪽값들을 전부 정렬했습니다. 따라서 현재               1 2 3 4 5 6 7 8 10 9 이며 피봇값8의 오른쪽을 퀵소트 해면 정렬이 완료됩니다.

소스코드 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
 
int number = 10;
int data[] = {1, 10, 5, 8, 7, 6, 4, 3, 2, 9};
 
void show() {
   int i;
   for(i = 0; i < number; i++) {
      printf("%d ", data[i]);
   }
}
 
void quickSort(int* data, int start, int end) {
   if (start >= end) { // 원소가 1개인 경우 그대로 두기 
      return;
   }
   
   int key = start; // 키는 첫 번째 원소
   int i = start + 1, j = end, temp;
   
   while(i <= j) { // 엇갈릴 때까지 반복
      while(i <= end && data[i] <= data[key]) { // 키 값보다 큰 값을 만날 때까지 
         i++;
      }
      while(j > start && data[j] >= data[key]) { // 키 값보다 작은 값을 만날 때까지 
         j--;
      }
      if(i > j) { // 현재 엇갈린 상태면 키 값과 교체 
         temp = data[j];
         data[j] = data[key];
         data[key] = temp;
      } else { // 엇갈리지 않았다면 i와 j를 교체 
         temp = data[i];
         data[i] = data[j];
         data[j] = temp;
      }
   } 
   
   quickSort(data, start, j - 1);
   quickSort(data, j + 1, end); 
}
 
int main(void) {
   quickSort(data, 0, number - 1);
   show();
   return 0;
}
cs
728x90
728x90

 

1.준비사항

2. SQL BBS테이블 생성

3.  NODEJS로 웹페이지 HELLO WORLD 띄우기

 

1.준비사항

 

 

NodeJS 설치 

ORACLE DATABASE18C EXPRESS EDITION설치

ORACLE SQL DEVELOPER 

 

 

 

오라클 DATABASE와 SQL DEVELOPER는  다음 링크에서 다운받으면 됩니다.

 

https://www.oracle.com/downloads/

 

NODE JS는 여기서 설치하시면됩니다.

최신버전보다 14.17.0 LST를 설치하는걸 추천합니다

https://nodejs.org/ko/

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

 

 

DATABASE와 SQL DEVELOPER 와 NODE JS설치가 성공적으로 되었을경우 

2. SQL문 작성

 

CREATE TABLE BBS(
    NO NUMBER(10) NOT NULL,
    TITLE VARCHAR(255),
    WRITER VARCHAR(100),
    CONTENT VARCHAR(4000),
    REGDATE DATE,
    OK NUMBER(1) DEFAULT 1,
    TEMP VARCHAR(100),
    PRIMARY KEY(NO)
);

COMMIT;
CREATE SEQUENCE bbs_seq START WITH 1 INCREMENT BY 1 MAXVALUE 100000 CYCLE NOCACHE;  --1부터 1씩증가 10만까지 글번호가 자동으로 증가하기위해 
SELECT * FROM BBS;

INSERT INTO BBS values(bbs_seq.NEXTVAL  , 'DB타이틀' , '이진솔', 'DB 글내용', sysdate,1);
INSERT INTO BBS values(bbs_seq.NEXTVAL  , 'DB타이틀2' , '이진솔2', 'DB 글내용2', sysdate,1);

CREATE SEQUENCE bbs_seq START WITH 1 INCREMENT BY 1 MAXVALUE 100000 CYCLE NOCACHE; 를 한이유는

각 글의 고유번호 NO1,2,3,4... 를 하나씩 증가시키기위해 작성한 SQL문이다.

 

3. HELLO WORLD 띄우기

const express = require('express');
const app = express();

const server = app.listen(3000, () =>{
    console.log('start server : localhost:3000!!');
});

app.set('views',__dirname + '/views'); //dirname 현재디렉토리
app.set('view engine','ejs');
app.engine('html',require('ejs').renderFile);

app.get('/',function(req,res){
    res.render('index.html')
//    res.send('hello world');
})

app.get('/about',function(req,res){
    res.send('about page')
})

 

실행은 CMD에서 node '파일명'.js 입력하시면 실행되며

성공적으로 실행됐을때 start server : localhost:3000!! 이 터미널에 출력될것이다.

728x90
728x90

단주 매매란?

 

주식 호가창을 보면 매수, 매도 체결 가격과 수량이 나타납니다. 호가창은 주식을 하는 사람이면 가장 쉽게 접할 수 있는 창인 만큼 속임수가 가득합니다. 그 중 단주매매는 호가창 매수1, 매도1 수량이 연속해서 계속 체결되는 것을 말합니다. 하기 그림의 예를 보시면 됩니다.

 

단주매매를 하는 이유?

 

실제 호가창에서 일어나는 단주매매의 체결 속도를 보시면 사람이 매수 주문을 넣고 바로 매도 주문을 넣고 이걸 반복해서 구현 할 수 있는 속도가 아닙니다. 즉 프로그램을 통해 매매를 하는 것입니다. 즉 세력들이 사용하는 매매입니다. 단주 매매가 일어나는 가격을 보면 매수는 한호가 위에서 매도는 한호가 아래에서 거래가 됩니다. 따라서 단주 매매가 발생하면 종목의 가격이 올랐다가 내렸다가 올랐다가 내렸다가를 반복하게 됩니다. 관심종목에 둔 사람들 눈에는 가격이 계속 변하는 것 처럼 보이게 되며 사람들의 이목을 끌게 됩니다. 이처럼 단주매매는 어떤 이유에서든 주가를 움직이는 세력이 사람들의 관심을 끌기 위해 사용합니다. 단주매매가 진행되는 호가창을 지켜보면 사람들의 반응과 세력의 행동을 볼 수 있습니다. 세력의 의도대로 곧 주가가 올라 갈 것 같으니 개미들이 사기 시작합니다.

 

실제로 아는분들은 단주매매를 쓰면서 몇천만원치를 매수해놓고 단주매매를 돌려 가격을 1~3%올린다음

빠르게 매도하여 빠진다고 합니다. 

 

주식에서는 단주매매시 경고1,2,3회 후 거래정지? 벌금으로 알고있는데 가상화폐 거래에서는 단주매매에 대한 제재하지 않습니다. 하지만 거래소쪽과 권장 통신(api주문)이 초당 8회 분당200회로 정해져있지만 딱히 아무런 제제를 당해본적이없어서 잘모르겠습니다.

 

가격은 15만원에 판매중입니다. jinsol0321 문의카톡

 

<작동영상 v1>

www.youtube.com/watch?v=6kr1p23H4uE

<작동영상 v2>

 

www.youtube.com/watch?v=FKlbRoaZgYU

 

 

 

 

 

<pyupbit 함수 정리>

 

pyupbit

Python Wrapper for Upbit API

Installation

파이썬 개발 환경으로 최신 버전의 Anaconda를 설치하세요. (Python3 버전용)

pip install pyupbit

pyjwt 모듈을 필요로 합니다. (pyjwt >= 2.0)

pip install pyjwt

Import

import pyupbit

Quotation API

  • Websocket은 초당 5회, 분당 100회 연결 요청할 수 있습니다.
  • 종목, 캔들, 체결, 티커, 호가 API는 분당 600회, 초당 10회 사용 가능합니다.

암호화폐 목록

get_tickers 함수는 업비트가 지원하는 모든 암호화폐 목록을 얻어옵니다.

print(pyupbit.get_tickers())
['KRW-BTC', 'KRW-DASH', 'KRW-ETH', 'BTC-NEO', 'BTC-ETH', 'BTC-LTC', ... ]

업비트가 지원하는 암호화폐 목록 중 특정 시장(fiat)에 매매가 가능한 목록만 얻어올 수 있습니다. KRW/BTC/USDT 시장을 조회할 수 있습니다.

print(pyupbit.get_tickers(fiat="KRW"))
['KRW-BTC', 'KRW-DASH', 'KRW-ETH', 'KRW-NEO', 'KRW-MTL', 'KRW-LTC', ...]

최근 체결가격

get_current_price 함수는 암호화폐의 현재가를 얻어옵니다. 함수로 티커를 넣어줘야 합니다.

print(pyupbit.get_current_price("KRW-BTC"))

float 타입의 현재가가 반환됩니다.

8392000.0

리스트에 여러 개의 티커를 입력해 한 번에 현재가를 조회할 수 있습니다.

print(pyupbit.get_current_price(["KRW-BTC", "KRW-XRP"]))

여러 종목을 조회한 경우 딕셔너리로 현재가를 리턴합니다.

{'KRW-BTC': 8300000.0, 'KRW-XRP': 511.0}

get_current_price 함수는 최대 100개의 암호화폐를 조회할 수 있습니다. 100개 이상일 경우 분할해서 반복 조회해야 합니다.

차트 데이터

get_ohlcv 함수는 고가/시가/저가/종가/거래량을 DataFrame으로 반환합니다.

df = pyupbit.get_ohlcv("KRW-BTC")
print(df.tail())

날짜가 오름차순으로 정렬돼 최근 날짜가 마지막에 위치합니다.

2021-03-21 09:00:00  67849000.0  68715000.0  65451000.0  67120000.0   8097.428878
2021-03-22 09:00:00  67064000.0  68380000.0  64345000.0  64725000.0   8366.410551
2021-03-23 09:00:00  64728000.0  66279000.0  63000000.0  65458000.0   9961.040596
2021-03-24 09:00:00  65458000.0  68370000.0  64500000.0  64777000.0  11366.404524
2021-03-25 09:00:00  64777000.0  65305000.0  63319000.0  64257000.0   2770.703203

count 파라미터는 조회 갯수를 지정합니다. 최근 영업일 부터 이전 count만큼의 이전 영업일까지 조회합니다. count 파라미터를 입력하지 않을 경우 default value는 200입니다.

df = pyupbit.get_ohlcv("KRW-BTC", count=5)
print(len(df))

위 코드는 최근 영업일 부터 과거 5개의 데이터가 조회됩니다.

5

interval 파라미터는 조회단위를 지정합니다. 파라미터에는 다음 값을 지정할 수 있습니다.

  • day/minute1/minute3/minute5/minute10/minute15/minute30/minute60/minute240/week/month
print(pyupbit.get_ohlcv("KRW-BTC", interval="day")              # 일봉 데이터 (5일)
print(pyupbit.get_ohlcv("KRW-BTC", interval="minute1"))         # 분봉 데이터
print(pyupbit.get_ohlcv("KRW-BTC", interval="week"))            # 주봉 데이터

to 파라미터에 입력된 이전 단위(interval)까지의 데이터를 데이터프레임으로 얻을 수 있습니다. 예를 들어, 다음 코드는 2020-10-10일 보다 하루 전인 2020-10-09을 까지의 200개 데이터를 조회합니다. 단위를 설정하지 않았으니 단위는 일봉입니다.

print(pyupbit.get_ohlcv("KRW-BTC", to="20201010"))

intervalminute1로 지정한 경우 2020-10-10 보다 1분 이전 (2020-10-09 23:59:00)까지의 200개 데이터를 반환합니다.

print(pyupbit.get_ohlcv("KRW-BTC", interval="minute1", to="20201010"))

기준 시간 단위로 shift된 일봉을 계산할 수도 있습니다.

예) 2019-06-01 12:00:00 ~ 2019-06-02 11:59:59

print(pyupbit.get_daily_ohlcv_from_base("KRW-BTC", base=12))

예) 2019-06-01 13:00:00 ~ 2019-06-02 12:59:59

print(pyupbit.get_daily_ohlcv_from_base("KRW-BTC", base=13))

매수/매도 호가

get_orderbook 함수는 매수/매도 호가 정보를 조회합니다.

print(pyupbit.get_orderbook(tickers="KRW-BTC"))

리스트 안에 딕셔너리로 호가정보가 들어있습니다.

  • market : 암호화폐 티커
  • timestamp : 조회시간 (단위 ms)
  • orderbook_units : 매도호가/매수호가 정보
[{'market': 'KRW-BTC', 'timestamp': 1532118943687, 'total_ask_size': 17.08116346, 'total_bid_size': 3.07150192, 'orderbook_units': [{'ask_price': 8390000.0, 'bid_price': 8389000.0, 'ask_size': 3.16057415, 'bid_size': 0.5515136}, {'ask_price': 8392000.0, 'bid_price': 8387000.0, 'ask_size': 0.71247596, 'bid_size': 0.95157819}, {'ask_price': 8393000.0, 'bid_price': 8386000.0, 'ask_size': 3.70536818, 'bid_size': 0.15824907}, {'ask_price': 8398000.0, 'bid_price': 8385000.0, 'ask_size': 0.00481809, 'bid_size': 0.00119147}, {'ask_price': 8399000.0, 'bid_price': 8383000.0, 'ask_size': 1.1228337, 'bid_size': 0.05}, {'ask_price': 8400000.0, 'bid_price': 8380000.0, 'ask_size': 0.48354827, 'bid_size': 0.00613734}, {'ask_price': 8401000.0, 'bid_price': 8375000.0, 'ask_size': 0.00433629, 'bid_size': 0.05}, {'ask_price': 8402000.0, 'bid_price': 8374000.0, 'ask_size': 2.7434153, 'bid_size': 0.32104953}, {'ask_price': 8420000.0, 'bid_price': 8373000.0, 'ask_size': 0.0028, 'bid_size': 0.5010063}, {'ask_price': 8428000.0, 'bid_price': 8370000.0, 'ask_size': 5.14099352, 'bid_size': 0.48077642}]}]

tickers 파라미터에 리스트로 티커를 넣으면, 한 번에 여러 종목의 호가를 조회할 수 있습니다.

print(pyupbit.get_orderbook(tickers=["KRW-BTC", "KRW-XRP"]))

Exchange API

주문은 초당 8회, 분당 200회 / 주문 외 요청은 초당 30회, 분당 900회 사용 가능합니다.

로그인

Access Key와 Sercret Key를 사용해서 Upbit 객체를 생성합니다. 이는 웹페이지에서 로그인하는 것과 같습니다.

access = "73kVqowGQOGEjdR31221j31j2ifekjkgjekgjekg"          # 본인 값으로 변경
secret = "egjekgj3iekeEEkej3i3j3iejjwiEejiejeEeijg"          # 본인 값으로 변경
upbit = Upbit(access, secret)

잔고 조회

get_balance 메서드는 입력받은 티커의 보유 수량 정보를 조회합니다.

print(upbit.get_balance("KRW-XRP"))     # KRW-XRP 조회
print(upbit.get_balance("KRW"))         # 보유 현금 조회

get_balances 메서드는 보유 중인 모든 암호화폐의 잔고 및 단가 정보를 딕셔너리로 조회합니다.

print(upbit.get_balances())
[{'currency': 'KRW',
  'balance': '0.34689181',
  'locked': '0.0',
  'avg_buy_price': '0',
  'avg_buy_price_modified': True,
  'unit_currency': 'KRW'},
 {'currency': 'BTC',
  'balance': '0.00174304',
  'locked': '0.0',
  'avg_buy_price': '64387000',
  'avg_buy_price_modified': False,
  'unit_currency': 'KRW'},]

지정가 매수/매도 주문

지정한 가격에 주문을 요청합니다. 다음은 원화 시장에 리플을 600원에 20개 매도 합니다.

# 매도
print(upbit.sell_limit_order("KRW-XRP", 600, 20))

주문 정보가 딕셔너리로 반환됩니다. uuid는 주문에 대한 고윳값으로 이를 사용해 추후 주문을 취소하거나 정정할 수 있습니다.

{'uuid': '0bcf0916-a7f5-49ed-80a9-a45e9e190cd3',
 'side': 'ask',
 'ord_type': 'limit',
 'price': '600.0',
 'state': 'wait',
 'market': 'KRW-XRP',
 'created_at': '2021-03-21T15:24:11+09:00',
 'volume': '20.0',
 'remaining_volume': '20.0',
 'reserved_fee': '0.0',
 'remaining_fee': '0.0',
 'paid_fee': '0.0',
 'locked': '20.0',
 'executed_volume': '0.0',
 'trades_count': 0}

다음은 원화 시장에 리플을 613원에 10개 매수 합니다.

# 매수
print(upbit.buy_limit_order("KRW-XRP", 613, 10))
{'uuid': '1907dcdc-2b96-4d85-9963-866f7aa220cd',
 'side': 'bid',
 'ord_type': 'limit',
 'price': '613.0',
 'state': 'wait',
 'market': 'KRW-XRP',
 'created_at': '2021-03-21T15:10:32+09:00',
 'volume': '10.0',
 'remaining_volume': '10.0',
 'reserved_fee': '3.065',
 'remaining_fee': '3.065',
 'paid_fee': '0.0',
 'locked': '6133.065',
 'executed_volume': '0.0',
 'trades_count': 0}

시장가 매수/매도 주문

시장가 매수는 매우선 매도호가에 즉시 매수합니다. buy_market_order 메서드로 티커와 매수 금액만을 입력합니다. 매수 금액은 수수료를 포함한 금액입니다. 다음 예제에서 주문한 10000원은 수수료가 포함된 금액입니다. 수수료가 0.05%라면 수수료를 제외한 9995원만이 주문에 사용됩니다.

print(upbit.buy_market_order("KRW-XRP", 10000))

다음은 리플 30개를 시장가 매도합니다. 매도대금이 총 10000원이라면 수수료를 제외한 금액이 입금됩니다. 만약 수수료가 0.05%라면 9995원 받을 수 있습니다.

print(upbit.sell_market_order("KRW-XRP", 30))

미체결 주문 조회

get_order 메서드는 입력된 암호화폐의 미체결 주문을 조회합니다.

upbit.get_order("KRW-LTC")

미체결 주문이 있다면 리스트로 상세 내역을 반환합니다. 다음은 250000원에 매도(ask) 주문한 LTC이 1개(volume)있다는 의미입니다.

[{'uuid': '50e184b3-9b4f-4bb0-9c03-30318e3ff10a',
  'side': 'ask',
  'ord_type': 'limit',
  'price': '250000.0',
  'state': 'wait',
  'market': 'KRW-LTC',
  'created_at': '2021-03-25T14:10:53+09:00',
  'volume': '1.0',
  'remaining_volume': '1.0',
  'reserved_fee': '0.0',
  'remaining_fee': '0.0',
  'paid_fee': '0.0',
  'locked': '1.0',
  'executed_volume': '0.0',
  'trades_count': 0}]

state 파라미터를 사용하면 완료된 주문을 조회할 수 있습니다.

print(upbit.get_order("KRW-LTC", state="done"))
[{'uuid': '0694def7-5ada-405f-b0f3-053801d5b190',
  'side': 'ask',
  'ord_type': 'market',
  'price': None,
  'state': 'done',
  'market': 'KRW-LTC',
  'created_at': '2021-03-21T14:43:40+09:00',
  'volume': '0.07336815',
  'remaining_volume': '0.0',
  'reserved_fee': '0.0',
  'remaining_fee': '0.0',
  'paid_fee': '8.39331636',
  'locked': '0.0',
  'executed_volume': '0.07336815',
  'trades_count': 1},
 {'uuid': '48d6d451-3db5-4357-9d5a-bfb8f417c943',
  'side': 'ask',
  'ord_type': 'limit',
  'price': '230000.0',
  'state': 'done',
  'market': 'KRW-LTC',
  'created_at': '2021-03-17T01:06:55+09:00',
  'volume': '0.5',
  'remaining_volume': '0.0',
  'reserved_fee': '0.0',
  'remaining_fee': '0.0',
  'paid_fee': '58.775',
  'locked': '0.0',
  'executed_volume': '0.5',
  'trades_count': 2}]

매수/매도 주문 취소

주문 함수의 리턴 값 중 uuid 값을 사용해서 주문을 취소할 수 있습니다.

print(upbit.cancel_order('50e184b3-9b4f-4bb0-9c03-30318e3ff10a'))

정상 처리됐다면 다음과 같이 딕셔너리가 반환됩니다.

{'uuid': '50e184b3-9b4f-4bb0-9c03-30318e3ff10a', 'side': 'ask', 'ord_type': 'limit', 'price': '250000.0', 'state': 'wait', 'market': 'KRW-LTC', 'created_at': '2021-03-25T14:10:53+09:00', 'volume': '1.0', 'remaining_volume': '1.0', 'reserved_fee': '0.0', 'remaining_fee': '0.0', 'paid_fee': '0.0', 'locked': '1.0', 'executed_volume': '0.0', 'trades_count': 0}

웹소켓

WebSocket을 이용해서 현재가, 호가, 체결에 대한 정보를 수신합니다.

  • 첫 번째 파라미터에는 수신정보를 입력하며 ticker, orderbook, transaction을 사용할 수 있습니다.
  • 두 번째 파라미터는 구독할 필터를 설정하며 암호화폐의 티커를 입력합니다. 현재 버전에서는 원화 시장만을 지원합니다.
from pyupbit import WebSocketManager

if __name__ == "__main__":
    wm = WebSocketManager("ticker", ["KRW-BTC"])
    for i in range(10):
        data = wm.get()
        print(data)
    wm.terminate()

주의: 웹소켓의 multiprocessing을 위해 __name__ guard를 반드시 써줘야 합니다.

PyQt5와 함께 웹소켓을 사용하는 예제는 다음 코드를 참고하세요.

  • 버튼을 클릭하면 웹소켓에서 가격정보를 가져와서 화면에 출력합니다.

 

 

<함수 자세히 보기 >

 

 

 

def get_tick_size(price):
    if price >= 2000000:
        tick_size = round(price / 1000) * 1000
    elif price >= 1000000:
        tick_size = round(price / 500) * 500
    elif price >= 500000:
        tick_size = round(price / 100) * 100
    elif price >= 100000:
        tick_size = round(price / 50) * 50
    elif price >= 10000:
        tick_size = round(price / 10) * 10
    elif price >= 1000:
        tick_size = round(price / 5) * 5
    elif price >= 100:
        tick_size = round(price / 1) * 1
    elif price >= 10:
        tick_size = round(price / 0.1) * 0.1
    else:
        tick_size = round(price / 0.01) * 0.01
    return tick_size


class Upbit:
    def __init__(self, access, secret):
        self.access = access
        self.secret = secret

    def _request_headers(self, query=None):
        payload = {
            "access_key": self.access,
            "nonce": str(uuid.uuid4())
        }

        if query is not None:
            m = hashlib.sha512()
            m.update(urlencode(query).encode())
            query_hash = m.hexdigest()
            payload['query_hash'] = query_hash
            payload['query_hash_alg'] = "SHA512"

        #jwt_token = jwt.encode(payload, self.secret, algorithm="HS256").decode('utf-8')
        jwt_token = jwt.encode(payload, self.secret, algorithm="HS256")     # PyJWT >= 2.0
        authorization_token = 'Bearer {}'.format(jwt_token)
        headers = {"Authorization": authorization_token}
        return headers

    # region balance
    def get_balances(self, contain_req=False):
        """
        전체 계좌 조회
        :param contain_req: Remaining-Req 포함여부
        :return: 내가 보유한 자산 리스트
        [contain_req == True 일 경우 Remaining-Req가 포함]
        """
        try:
            url = "https://api.upbit.com/v1/accounts"
            headers = self._request_headers()
            result = _send_get_request(url, headers=headers)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def get_balance(self, ticker="KRW", contain_req=False):
        """
        특정 코인/원화의 잔고를 조회하는 메소드
        :param ticker: 화폐를 의미하는 영문 대문자 코드
        :param contain_req: Remaining-Req 포함여부
        :return: 주문가능 금액/수량 (주문 중 묶여있는 금액/수량 제외)
        [contain_req == True 일 경우 Remaining-Req가 포함]
        """
        try:
            # fiat-ticker
            # KRW-BTC
            if '-' in ticker:
                ticker = ticker.split('-')[1]

            balances, req = self.get_balances(contain_req=True)

            # search the current currency
            balance = 0
            for x in balances:
                if x['currency'] == ticker:
                    balance = float(x['balance'])
                    break

            if contain_req:
                return balance, req
            else:
                return balance
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def get_balance_t(self, ticker='KRW', contain_req=False):
        """
        특정 코인/원화의 잔고 조회(balance + locked)
        :param ticker: 화폐를 의미하는 영문 대문자 코드
        :param contain_req: Remaining-Req 포함여부
        :return: 주문가능 금액/수량 (주문 중 묶여있는 금액/수량 포함)
        [contain_req == True 일 경우 Remaining-Req가 포함]
        """
        try:
            # KRW-BTC
            if '-' in ticker:
                ticker = ticker.split('-')[1]

            balances, req = self.get_balances(contain_req=True)

            balance = 0
            locked = 0
            for x in balances:
                if x['currency'] == ticker:
                    balance = float(x['balance'])
                    locked = float(x['locked'])
                    break

            if contain_req:
                return balance + locked, req
            else:
                return balance + locked
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def get_avg_buy_price(self, ticker='KRW', contain_req=False):
        """
        특정 코인/원화의 매수평균가 조회
        :param ticker: 화폐를 의미하는 영문 대문자 코드
        :param contain_req: Remaining-Req 포함여부
        :return: 매수평균가
        [contain_req == True 일 경우 Remaining-Req가 포함]
        """
        try:
            # KRW-BTC
            if '-' in ticker:
                ticker = ticker.split('-')[1]

            balances, req = self.get_balances(contain_req=True)

            avg_buy_price = 0
            for x in balances:
                if x['currency'] == ticker:
                    avg_buy_price = float(x['avg_buy_price'])
                    break
            if contain_req:
                return avg_buy_price, req
            else:
                return avg_buy_price

        except Exception as x:
            print(x.__class__.__name__)
            return None

    def get_amount(self, ticker, contain_req=False):
        """
        특정 코인/원화의 매수금액 조회
        :param ticker: 화폐를 의미하는 영문 대문자 코드 (ALL 입력시 총 매수금액 조회)
        :param contain_req: Remaining-Req 포함여부
        :return: 매수금액
        [contain_req == True 일 경우 Remaining-Req가 포함]
        """
        try:
            # KRW-BTC
            if '-' in ticker:
                ticker = ticker.split('-')[1]

            balances, req = self.get_balances(contain_req=True)

            amount = 0
            for x in balances:
                if x['currency'] == 'KRW':
                    continue

                avg_buy_price = float(x['avg_buy_price'])
                balance = float(x['balance'])
                locked = float(x['locked'])

                if ticker == 'ALL':
                    amount += avg_buy_price * (balance + locked)
                elif x['currency'] == ticker:
                    amount = avg_buy_price * (balance + locked)
                    break
            if contain_req:
                return amount, req
            else:
                return amount
        except Exception as x:
            print(x.__class__.__name__)
            return None

    # endregion balance

    # region chance
    def get_chance(self, ticker, contain_req=False):
        """
        마켓별 주문 가능 정보를 확인.
        :param ticker:
        :param contain_req: Remaining-Req 포함여부
        :return: 마켓별 주문 가능 정보를 확인
        [contain_req == True 일 경우 Remaining-Req가 포함]
        """
        try:
            url = "https://api.upbit.com/v1/orders/chance"
            data = {"market": ticker}
            headers = self._request_headers(data)
            result = _send_get_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    # endregion chance

    # region order
    def buy_limit_order(self, ticker, price, volume, contain_req=False):
        """
        지정가 매수
        :param ticker: 마켓 티커
        :param price: 주문 가격
        :param volume: 주문 수량
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/orders"
            data = {"market": ticker,
                    "side": "bid",
                    "volume": str(volume),
                    "price": str(price),
                    "ord_type": "limit"}
            headers = self._request_headers(data)
            result = _send_post_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def buy_market_order(self, ticker, price, contain_req=False):
        """
        시장가 매수
        :param ticker: ticker for cryptocurrency
        :param price: KRW
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/orders"
            data = {"market": ticker,  # market ID
                    "side": "bid",  # buy
                    "price": str(price),
                    "ord_type": "price"}
            headers = self._request_headers(data)
            result = _send_post_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def sell_market_order(self, ticker, volume, contain_req=False):
        """
        시장가 매도 메서드
        :param ticker: 가상화폐 티커
        :param volume: 수량
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/orders"
            data = {"market": ticker,  # ticker
                    "side": "ask",  # sell
                    "volume": str(volume),
                    "ord_type": "market"}
            headers = self._request_headers(data)
            result = _send_post_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def sell_limit_order(self, ticker, price, volume, contain_req=False):
        """
        지정가 매도
        :param ticker: 마켓 티커
        :param price: 주문 가격
        :param volume: 주문 수량
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/orders"
            data = {"market": ticker,
                    "side": "ask",
                    "volume": str(volume),
                    "price": str(price),
                    "ord_type": "limit"}
            headers = self._request_headers(data)
            result = _send_post_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def cancel_order(self, uuid, contain_req=False):
        """
        주문 취소
        :param uuid: 주문 함수의 리턴 값중 uuid
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/order"
            data = {"uuid": uuid}
            headers = self._request_headers(data)
            result = _send_delete_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None

    def get_order(self, ticker, state='wait', kind='normal', contain_req=False):
        """
        주문 리스트 조회
        :param ticker: market
        :param state: 주문 상태(wait, done, cancel)
        :param kind: 주문 유형(normal, watch)
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        # TODO : states, uuids, identifiers 관련 기능 추가 필요
        try:
            url = "https://api.upbit.com/v1/orders"
            data = {'market': ticker,
                    'state': state,
                    'kind': kind,
                    'order_by': 'desc'
                    }
            headers = self._request_headers(data)
            result = _send_get_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None
    # endregion order

    def get_individual_order(self, uuid, contain_req=False):
        """
        주문 리스트 조회
        :param uuid: 주문 id
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        # TODO : states, uuids, identifiers 관련 기능 추가 필요
        try:
            url = "https://api.upbit.com/v1/order"
            data = {'uuid': uuid}
            headers = self._request_headers(data)
            result = _send_get_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None
    # endregion order

    def withdraw_coin(self, currency, amount, address, secondary_address='None', transaction_type='default', contain_req=False):
        """
        코인 출금
        :param currency: Currency symbol
        :param amount: 주문 가격
        :param address: 출금 지갑 주소
        :param secondary_address: 2차 출금주소 (필요한 코인에 한해서)
        :param transaction_type: 출금 유형
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/withdraws/coin"
            data = {"currency": currency,
                    "amount": amount,
                    "address": address,
                    "secondary_address": secondary_address,
                    "transaction_type": transaction_type}
            headers = self._request_headers(data)
            result = _send_post_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None
    
    def withdraw_cash(self, amount: str, contain_req=False):
        """
        현금 출금
        :param amount: 출금 액수
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/withdraws/krw"
            data = {"amount": amount}
            headers = self._request_headers(data)
            result = _send_post_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None
    
    def get_individual_withdraw_order(self, uuid: str, currency: str, contain_req=False):
        """
        현금 출금
        :param uuid: 출금 UUID
        :param txid: 출금 TXID
        :param currency: Currency 코드
        :param contain_req: Remaining-Req 포함여부
        :return:
        """
        try:
            url = "https://api.upbit.com/v1/withdraw"
            data = {"uuid": uuid, "currency": currency}
            headers = self._request_headers(data)
            result = _send_get_request(url, headers=headers, data=data)
            if contain_req:
                return result
            else:
                return result[0]
        except Exception as x:
            print(x.__class__.__name__)
            return None


if __name__ == "__main__":
    import pprint
    with open("../upbit.txt") as f:
        lines = f.readlines()
        access = lines[0].strip()
        secret = lines[1].strip()

    # Exchange API 사용을 위한 객체 생성
    upbit = Upbit(access, secret)

    #-------------------------------------------------------------------------
    # Exchange API
    #-------------------------------------------------------------------------
    # 자산 - 전체 계좌 조회
    balances = upbit.get_balances()
    pprint.pprint(balances)

    # 원화 잔고 조회
    print(upbit.get_balance(ticker="KRW"))          # 보유 KRW
    print(upbit.get_amount('ALL'))                  # 총매수금액
    print(upbit.get_balance(ticker="KRW-BTC"))      # 비트코인 보유수량
    print(upbit.get_balance(ticker="KRW-XRP"))      # 리플 보유수량

    #print(upbit.get_chance('KRW-HBAR'))
    #print(upbit.get_order('KRW-BTC'))

    # 매도
    # print(upbit.sell_limit_order("KRW-XRP", 1000, 20))

    # 매수
    # print(upbit.buy_limit_order("KRW-XRP", 200, 20))

    # 주문 취소
    # print(upbit.cancel_order('82e211da-21f6-4355-9d76-83e7248e2c0c'))

    # 시장가 주문 테스트
    # upbit.buy_market_order("KRW-XRP", 10000)

    # 시장가 매도 테스트
    # upbit.sell_market_order("KRW-XRP", 36)

 

728x90
728x90

해당글은 외주를 받아 제작하게 되었습니다.  카톡jinsol0321 

 

주식에서는 순간체결량(키움증권 [0148])이라는 기능을 HTS에서 제공합니다.

 

순간체결량은 순간적으로 한 종목에 집중되거나 한번에 대규모 주문이 실행될 경우 해당 종목의 체결량이 순간적으로 늘어나게 되는데, 이러한 대규모 주문이 집중되는 경우는 순간펌핑,설거지 , 공시 등 다양한 이유가 존재합니다.

이러한 순간적인 높은 체결량을 사람눈으로 120개 가까이되는 코인들을 전부 체크하기란 불가능에 가깝습니다.

 

개발하고자 하는 프로그램은 가상화폐거래소 Upbit에서 KRW마켓에 모든코인 117개를 매초마다 최근 1분봉 OR 3분봉 파싱하여(거래량,가격)

 

순간체결금액이 사용자가 설정한금액보다 높은값의 거래량이 터졌을때 알람이 가도록 하는 프로그램을 개발하는게

 

목표입니다. 

 

ex) 사용자의 설정값이 1분봉 50억이라고 설정햇을때 펀디엑스에서 최근 1분봉 거래량이 50억을 넘었을때 프로그램에서 알람이 울리며, 텔레그램으로도 알람이 가도록 프로그램이 작동합니다. 

 

 

개발과정에서 순간체결량이 조건을 달성했을때 친숙한 sound를 재생하게 하려했지만, UTF-8 오류로 인해 그냥 

winsound에서 100헤르츠 소리를 나도록설정하였습니다.(오래듣기 싫은소리)

 

사용라이브러리

 

 

해당 프로그램을 실행하기위해서는 python3.7.9버전과 해당 라이브러리들을 설치해야 실행됩니다.

 

1분봉 감시

www.youtube.com/watch?v=Cv4z3EeyaAY

 

 

3분봉 감시

www.youtube.com/watch?v=fuIXqPKW1vk

 

728x90
728x90

액션바 오른쪽위 메뉴인 옵션메뉴 뷰를 사용해보자.

onCreateOptionsMenu()메서드를 오버라이드 하여 옵션메뉴를 생성한다.

 

옵션메뉴 안에있는 메뉴를 클릭했을때 발생하는 이벤트처리는 

onOptionsItemSelected() 메서드를 오버라이드하여 처리한다. 

 

옵션메뉴를 생성하는 방법에는 두가지가있다. 

1. 메뉴xml을 이용해서 만드는방법과

2. kt파일에서 하드코딩하여 옵션을 만드는 방법이 있다.

 

1. menu1레이아웃을 먼저 만든다.

 

 

 

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    >
    
    <item
        android:id = "@+id/itemRed"
        android:title=" 배경색 (빨강)"
        tools:ignore="MissingConstraints">
    </item>



    <item
        android:id = "@+id/itemGreen"
        android:title=" 배경색 (초록)"
        tools:ignore="MissingConstraints">
    </item>


    <item
        android:id = "@+id/itemBlue"
        android:title=" 배경색 (파랑)"
        tools:ignore="MissingConstraints">
    </item>

    <item android:title="버튼변경 >> ">
        <menu>
            <item
                android:id="@+id/subRotate"
                android:title="버튼 45도 회전"/>
            <item
                android:id="@+id/subSize"
                android:title="버튼 2배 확대">
            </item>
        </menu>
    </item>
</menu>

 

파일명은 menu1.xml파일이다 

 

코드를 설명하면 menu1.xml파일은 3개의 아이템이 각각 존재하며

버튼변경>> 이라는 하나의 아이템속 메뉴안에 두개의 아이템이 존재한다.

item을 선언할때 꼭 id값과 title값을 까먹지말고 정의해야 한다.

 

 

이제 메인엑티비티.kt파일에서 오버라이드하여 메뉴를 활성시켜야된다.

 

 

 

 

 override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        super.onCreateOptionsMenu(menu)
        var mInflater = menuInflater
        mInflater.inflate(R.layout.menu1, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId){
            R.id.itemRed ->{
                baselayout.setBackgroundColor(Color.RED)
                return true
            }
            R.id.itemBlue ->{
                baselayout.setBackgroundColor(Color.BLUE)
                return true
            }
            R.id.itemGreen ->{
                baselayout.setBackgroundColor(Color.GREEN)
                return true
            }
            R.id.subRotate ->{
                //돌리기
                button1.rotation = 45f
                return true

            }
            R.id.subSize -> {
                //확대


                button1.scaleX = 2f
                return true
            }
        }

        return super.onOptionsItemSelected(item)
    }

}

 

 

 

2. 하드코딩을 통한 옵션메뉴 만들기

 

옵션메뉴 만들기

override fun onCreateOptionsMenu(menu: Menu?): Boolean {

         menu!!.add(0, 1, 0, "배경색 (빨강)")
         menu!!.add(0, 2, 0, "배경색 (초록)")
         menu!!.add(0, 3, 0, "배경색 (파랑)")
         menu!!.add(0, 3, 0, "버튼 확대")
         menu!!.add(0, 3, 0, "버튼 돌리기")
         return super.onCreateOptionsMenu(menu)
     }

 

옵션메뉴 클릭이벤트 처리 

 

 

 

override fun onOptionsItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
             1 -> {
                 baselayout.setBackgroundColor(Color.RED)
                 return true
             }
             2 -> {
                 baselayout.setBackgroundColor(Color.BLUE)
                 return true
             }
             3 -> {
                 baselayout.setBackgroundColor(Color.GREEN)
                 return true
             }
             4->{
                //버튼확대
             }
             5->{
                 //버튼돌리기기
             }

         }
     return true
     }
728x90
728x90

배열과 연결리스트 두 자료구조 모두 데이터를 나열한다는 점에서 비슷하게 생각할수있습니다.

 

그러나 두 자료구조는 확실한 차이가 있습니다.

 

배열의 경우 사용이 매우 간단하다는 장점이 있는 반면, 배열의 가장 큰 단점은 크기가 고정된다는 점이다.

 

프로그램이 실행이 되고 나면 배열의 크기를 줄이거나 늘릴수없습니다. 

 

배열의 크기를 잘못 예측하여 실제보다 작은 크기로 선언할경우 저장공간이 부족하게되고 너무 큰 크기로 배열을 선언하면 메모리 저장공간을 낭비하게 됩니다

 

배열과 같이 프로그램이 실행전 메모르 크기가 결정되는 메모리할당 방법을 정적메모리 할당이라 합니다.

 

이러한 단점들을 보완하는 자료구조가 대표적으로 연결리스트(linked list)가 존재합니다.

 

연결리스트(linked list)의경우 동적메모리 할당을 이용하여 배열과는 다르게 선형 데이터 구조를 이루고 있으며

 

일종의 끈처럼 데이터 구조를 표현할 수 있다.

 

 

 

연결리스트는 배열이 가진 단점을 극복해내는 자료구조이다. 연결리스트는 크기를 동적으로 변경할수 있기 때문에

 

실행 도중 필요한 만큼 메모리를 확보할 수 있고, 필요없는 메모리는 삭제가 가능하다.

 

연결리스트의 단점으로는 포인터를 사용하기 때문에 사용법이 어렵고 오류가 났을때 문제점이 무엇인지 찾기 어렵다는점이다.

 

 


동적 메모리 할당


 

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int	main(void){
	
	int *ptr = NULL;
	p2i = (int *)malloc(5*sizeof(int));
	
	//~~~~~
	
	free(p2i); 
}

 

malloc() 함수의 경우 stdlib.h헤더파일에 정의되어있으니 헤더파일을 포함하여야 한다.

malloc() 함수는 메모리를 할당받는 함수로 free 함수를 통해 메모리를 반납한다.

malloc() 함수는 반환되는 주소의 타입이 void* 이므로 주소를 받는 포인터에 맞춰 명시적인 타입 변환을 시켜주어야 한다.

 

예제4.1 ) 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Movie_Strcut{
	char title[20]; //제목 
	int release; //개봉년도 
	int viewers; //관객수 
}movie;

int	main(void){
	
	int *iptr = (int *)malloc(sizeof(int));
	movie *mptr = (movie*)malloc(sizeof(movie));
	
	if((iptr == NULL )or(mptr == NULL)){
		printf("메모리 할당실패 \n");
		return (1);
	}
	*iptr = 20;
	printf("iptr 메모리할당후 : %d \n\n",*iptr);
	free(iptr);
	strcpy(mptr->title,"미나리");
	mptr->release = 2021;
	mptr->viewers = 100000;
	printf("mptr 메모리 할당후 제목 : %s		개봉연도: %d		관객수 %d",mptr->title,mptr->release,mptr->viewers);
	free(mptr);

	return 0;	
}

 


연결리스트(Linked list)


 

연결리스트는 하나의 구조체안에 필드로 다음 구조체를 가르키는 포인터와 데이터를 필드로 갖는 구조체를 의미한다.

 

예제) 단순 연결리스트 다루기 기초

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node{
	int data;
	struct Node* link;
}Node;

int main(){
	Node *head, *temp;
	head = (Node *)malloc(sizeof(Node));
	
	if(head ==NULL)	exit(1);
	
	head->data = 10;
	head->link = NULL;
	
	temp = (Node *)malloc(sizeof(Node));
	if(temp ==NULL)	exit(1);
	
	temp->data = 20;
	temp->link = NULL;
	head->link = temp;
	
	printf("head-> %d ->%d \n",head->data, head->link->data);
	free(temp);
	free(head);
	
	return 0;
}

 

단순연결리스트 함수들

함수 설명 반환값  
create_node 동적으로 노드를 생성 노드 포인터  
count_nodes 연결리스트의 길이를 계산 길이  
search_node 연결리스트의 노드를 탐색 노드 포인터  
insert_node 연결리스트에 노드를 상비 없음  
delete_node 연결리스트에서 노드를 삭제 노드 포인터  
concatenate_lists 두 연결리스트의 결합 헤드 포인터  
reverse_list 연결리스트 순서를 반대로 변경 헤드포인터  

 

 

이어보기 

728x90
728x90

코틀린 기본 문법정리

2강에서 build.gradle 앱수준에서

plugins부분에 id 'kotlin-android-extensions' 을 추가하였다

목차 

 

1. 자료형,변수,값 선언

2. 리스트

3. 흐름제어(when , for)

4. 함수정의

5. 클래스,함수 정의

6. 상속

7. 람다식

 

코틀린은 값의 변경여부를 중요하게 생각합니다.

그래서 항상 변수를 선언할때 이변수가 변경가능한 변수인지, 변경이 불가능한 변수인지 키워드를 통해 정의합니다.

 

val : 변경 불가능한 값

var : 변경 가능한 값 

 

fun main(){
    var a:Int = 10
    val b:Int = 20
    a = 20
    b = 40 // b는 val(변경불가능한상수)로 정의했기때문에 값을변경할수없음 오류
}

 

Nullable

 

코틀린은 변경가능한 변수인지도 중요하게 여기지만, 해당 변수가 null값이 들어갈수 있는지 아닌지 또한 중요하게 여기고있습니다. 

 

 

 

<코드설명>

9: c는 변경이 가능한 Int형변수로 3으로 초기화해줌

10: c에 null값을 넣었지만 c는 null값이 들어갈수없는 변수이므로 에러

11. d는 변경이 가능한 Int형변수로 4로 초기화해주며 null값이 들어갈수있음

12. d에 null값을 넣어줌

 

 

LIST

 

코틀린에서의 리스트는 크게 두가지로 나눌수있습니다

1. List<>와 

2. MutableList<>

 

List의 경우 값을 변경 삭제  추가가 되지않습니다.

반면 MutableList의 경우 배열의 요소를 변경, 추가 , 삭제가 가능합니다.

 

 

흐름제어(반복문 for , when)

 

for

 

 

when

 

자바에서의 switch문과 비슷하지만 아주 조금 다르다

default대신 else를 사용하며 , ->를 사용하며 in 6..15등을 사용한다(6~15)

 

 

문자열 템플릿

  • + : 문자열 붙이기
  • ``$변수명,${변수명}` : 문자열 중간에 변수가 들어가야 할 경우

val str1 = "안녕" val str2 = "하세요" println(str1+str2) // 안녕하세요

 

 

배열

  • arrayOf()
  • 배열의 생성과 초기화를 함께 수행 / 컴파일러가 자료형을 유추할 수 있을 때는 이를 생략!
  • 배열의 요소에 접근하려면 [] 대괄호에 인덱스적으면 됨

배열,리스트 선언시 <>안에 특정 자료형을 넣어서 정의했을경우 그배열은 그 자료형값만 들어갈수있음

 

함수정의

 

코틀린에서는 함수를 정의할때 fun 키워드를 사용합니다.

 

728x90
728x90

ititit1.tistory.com/37

 

판매) 업비트 호가 흔들기 프로그램 / 업비트 단주매매 프로그램 판매 2021-03-24

2021-02-19 업비트api변경, 최소주문액변경 등 옛날 단주프로그램으로 실행되지않습니다. 업비트 단주매매 프로그램 판매중 문의 jinsol0321 카톡 1.1 준비과정 (업비트 Open key 발급) 우선 업비트 계정

ititit1.tistory.com

이 글을 올리고나서 엄청높은조회수, 많은 제작문의를 받아왔는데 해당글은 배포용이 아니라 개발공부용으로 올린글이었습니다. 

또한 최근에 업비트 api 변경(docs.upbit.com/changelog/%EC%95%88%EB%82%B4-open-api-%EB%B3%80%EA%B2%BD%EC%82%AC%ED%95%AD-%EC%95%88%EB%82%B4-%EC%A0%81%EC%9A%A9-%EC%9D%BC%EC%9E%90-0322-1) , 최소주문금액500->5000원으로 변경 되면서 새로 단주매매프로그램을  개발하게 되었고

이번엔 유저 배포용으로 프로그램을 만들었습니다.

 

단주매매 프로그램가격은 150,000원에 판매중이며 문의시 자세히 설명해드리고, 문제생기거나 어려운부분은 친절히 도와드리겠습니다. jinsol0321 카톡

 

 

 

 

현재 만들어진 프로그램 기능은 1. 업비트 호가창 흔들기(단주매매)입니다.

 

 

제작문의로 들어온 김프프로그램(거래소와 선물거래소 가격차이를 이용한 리스크없는 매매프로그램) 을 개발중이며 이또한 개발이 잘된다면 유료배포 할생각입니다.

 

단주 매매란?

 

주식 호가창을 보면 매수, 매도 체결 가격과 수량이 나타납니다. 호가창은 주식을 하는 사람이면 가장 쉽게 접할 수 있는 창인 만큼 속임수가 가득합니다. 그 중 단주매매는 호가창 매수1, 매도1 수량이 연속해서 계속 체결되는 것을 말합니다. 하기 그림의 예를 보시면 됩니다.

 

단주매매를 하는 이유?

 

실제 호가창에서 일어나는 단주매매의 체결 속도를 보시면 사람이 매수 주문을 넣고 바로 매도 주문을 넣고 이걸 반복해서 구현 할 수 있는 속도가 아닙니다. 즉 프로그램을 통해 매매를 하는 것입니다. 즉 세력들이 사용하는 매매입니다. 단주 매매가 일어나는 가격을 보면 매수는 한호가 위에서 매도는 한호가 아래에서 거래가 됩니다. 따라서 단주 매매가 발생하면 종목의 가격이 올랐다가 내렸다가 올랐다가 내렸다가를 반복하게 됩니다. 관심종목에 둔 사람들 눈에는 가격이 계속 변하는 것 처럼 보이게 되며 사람들의 이목을 끌게 됩니다. 이처럼 단주매매는 어떤 이유에서든 주가를 움직이는 세력이 사람들의 관심을 끌기 위해 사용합니다. 단주매매가 진행되는 호가창을 지켜보면 사람들의 반응과 세력의 행동을 볼 수 있습니다. 세력의 의도대로 곧 주가가 올라 갈 것 같으니 개미들이 사기 시작합니다.

 

실제로 아는분들은 단주매매를 쓰면서 몇천만원치를 매수해놓고 단주매매를 돌려 가격을 1~3%올린다음

빠르게 매도하여 빠진다고 합니다. 

 

주식에서는 단주매매시 경고1,2,3회 후 거래정지? 벌금으로 알고있는데 가상화폐 거래에서는 단주매매에 대한 제재하지 않습니다. 하지만 거래소쪽과 권장 통신(api주문)이 초당 8회 분당200회로 정해져있지만 딱히 아무런 제제를 당해본적이없어서 잘모르겠습니다. 

 

 

 

www.youtube.com/watch?v=giuPsSeB73w&feature=emb_title

 

728x90
728x90

Flask는 웹개발을 위한 파이썬 프레임워크입니다.

 

파이썬을 이용하여 웹개발 할 때 많이 쓰이는 프레임워크는 장고(Django)와 (Falsk)가 있습니다.

 

Flask는 장고에 비해 가벼우며 초보입장에서 사용이 간단하며 최대한 가볍게 개발하기 좋은 프레임워크는 Flask입니다.

 

먼저 Python은 설치되어있다고 가정하고 진행하겠습니다.

 

1. 라이브러리 설치

 

pip3 install flask 

pip3 install pymysql

pip3 install pyopenssl

 

2. 프로젝트 폴더를 생성하고 가상환경 만들기.

 

파이썬 가상환경에 대해서 생소하신분들이 있을거같아서 가상환경 만들기 방법을 알려드리겠습니다. 

 

가상환경을 사용하는이유는 파이썬 라이브러리간 의존성 때문에 사용합니다.  패키지 버전을 업데이트할때 다른것들이 호환되지않아 문제가 생기는 경우가 나중에 자주발생하기때문에 가상환경을 사용합니다.

제 개인적인 경험으로는 파이썬 LSTM 인공신경망을 이용하여 주가예측 프로젝트를 진행할때 라이브러리 충돌로 엄청 애를 먹었던거같습니다... 

 

가상환경 생성방법

프로젝트를 사용할 폴더를 만든후 CMD에서 해당폴더로 CD를 통해 들어간후 

C:\Users\Jinsol\Desktop\my_project>python -m venv 가상환경이름 을 치시면 되는데

보통 가상환경이름은 venv로 사용하시는게 편할것입니다 따라서

1. cd 프로젝트폴더

2. 프로젝트폴더에서 python -m venv venv

 

이렇게하시면 프로젝트폴더에 venv라는 가상환경이 설치됩니다.

 

 

가상환경 활성화/비활성화

 

venv\Scripts\activate.bat -> 활성화

 

deactivate -> 비활성화

 

가상환경 내 패키지 설치 삭제

pip install

pip uninstall

 

3. Hello World 띄우기

 

venv가상환경폴더에 app.py 를 생성한후 코드를 작성합니다.

 

 

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(debug=True)

저장후 

app.py을 실행하면

 

이런식으로 뜰것이며 

http://127.0.0.1:5000/에 들어가면 본인의 웹페이지가 다음과같이 나올것입니다.!

 

728x90

+ Recent posts