반응형

전체 글 247

주가가 30% 떨어졌는데 PER은 왜 더 높아질까?

주가가 고점에서 30% 내려오면 예전보다 싸 보입니다. 같은 주식을 더 적은 돈으로 살 수 있는 것은 맞지만, 이익에 비해 싸졌는지는 별도로 봐야 합니다. 같은 기준의 양수 주당순이익(EPS)이 주가보다 더 큰 비율로 줄면 PER은 오히려 올라갈 수 있습니다.PER은 주가를 EPS로 나눈 값입니다. 주가 차트만 보고 할인율을 계산하기 전에, 분모에 넣은 이익이 그대로인지부터 확인할 필요가 있습니다.주가는 30%, 예상 이익은 50% 줄었다면가상의 기업을 놓고 계산해 보겠습니다. 처음 주가는 100달러, 특정 회계연도의 예상 EPS는 5달러입니다. 이후 주가가 70달러로 떨어졌습니다. 비교하는 EPS는 두 시점 모두 같은 회계연도·같은 산정 기준의 예상치이며, 주식분할 등 주당 수치를 바꾸는 사건은 없다고..

async 함수가 throw했는데 assert.throws 테스트는 실패한다면

비동기 함수 안에서 분명히 throw를 했는데 테스트에는 “Missing expected exception”이 나타날 수 있다. Node.js의 assert.throws로 검사했다면, 예외가 전달되는 경로부터 확인하자. 호출 순간 던져지는 예외와 반환된 Promise의 거부는 검사 방법이 다르다.await가 없는 async 함수도 Promise를 반환한다다음은 동작을 재현하기 위한 가상 이름 검증 함수다. 네트워크나 실제 사용자 자료는 사용하지 않는다. 코드를 validate.test.mjs로 저장한다. 테스트 대상은 빈 문자열을 거부하지만, 아래 테스트 작성 방식은 잘못됐다.import test from 'node:test';import assert from 'node:assert/strict';asy..

채권 ETF도 만기까지 기다리면 원금을 돌려받을까?

국고채 10년물 ETF를 사서 10년을 기다리면 매수한 돈이 돌아올까요? 일반 채권 ETF는 내가 산 날부터 만기를 세어 원금을 상환하는 상품이 아닙니다. ETF가 담은 채권의 만기와 ETF 자체의 존속기한을 구분해야 합니다.만기매칭형 채권 ETF에는 끝나는 시점이 따로 있지만, 이 경우에도 내가 낸 매수금액을 보장하는 것은 아닙니다. 나중에 쓸 돈을 넣어 두려는 목적이라면 이 차이부터 확인하는 편이 좋겠습니다.편입 채권은 만기가 와도 ETF는 계속될 수 있습니다일반적인 고정금리·만기일시상환 채권은 발행자가 약속을 정상적으로 이행한다는 전제에서 정해진 이자와 만기 상환금을 받는 구조입니다. 조기상환권이나 별도 조건이 붙은 채권은 발행 조건을 따로 봐야 합니다. 이때 상환의 기준은 발행 조건에 정해진 액면..

Stream.toList()로 만든 목록에 add가 안 된다면

Java에서 스트림 결과를 List로 받았는데 add 한 줄에서 UnsupportedOperationException이 발생할 수 있다. 특히 collect(Collectors.toList())를 더 짧은 toList()로 바꾼 뒤라면, 결과 목록의 수정 가능 여부부터 확인하자. 변수의 선언형이 List라는 사실만으로 추가·삭제가 보장되지는 않는다.짧아진 코드에 다른 계약이 붙는다아래는 문제를 재현하기 위한 가상 예제다. Demo.java로 저장해 javac Demo.java와 java Demo를 차례로 실행하면 add에서 예외가 난다. Stream.toList()는 Java 16부터 제공되므로 Java 8이나 11에서는 이 코드 자체가 컴파일되지 않는다.import java.util.List;impor..

ETF는 올랐는데 내 계좌는 왜 손실일까?

ETF 가격이 투자 시작 때보다 높아도, 중간에 추가로 산 계좌는 손실일 수 있습니다. 처음 산 돈과 나중에 넣은 돈이 같은 가격 변화를 겪지 않았기 때문입니다. 차트의 상승률과 내 손익이 다르다면 매수 날짜와 금액부터 나눠 볼 필요가 있습니다.특히 가격이 오른 뒤 투자금을 늘렸다면, 앞서 적은 돈으로 얻은 이익보다 뒤에 큰돈으로 겪은 손실이 커질 수 있습니다. ETF의 전체 기간 상승률만으로는 이 차이가 보이지 않습니다.가격은 8% 상승, 계좌에는 4만 원 손실실제 상품이 아닌 가상의 ETF를 생각해 보겠습니다. 가격은 10,000원에서 12,000원으로 오른 뒤 10,800원이 됩니다. 처음과 끝만 비교하면 8% 상승입니다. 분배금·수수료·세금·환율 변화는 없다고 가정합니다.처음에는 100만 원을 입..

파일 이름을 바꿨더니 Git 이력이 끊겼다면: log --follow

파일을 정리한 뒤 현재 이름으로 이력을 조회했는데, 이름을 바꾼 커밋 하나만 보일 때가 있다. 예전 수정 기록이 삭제됐다고 판단하기 전에 조회 경로와 --follow 옵션부터 확인해 보자.이름이 바뀌기 전의 경로는 다르다아래는 실제 프로젝트와 무관한 가상 예제다. Bash에서 새 임시 저장소를 만들고 같은 파일에 생성, 수정, 이름 변경을 차례로 커밋한다. 기존 프로젝트에서는 실행하지 않는다. 작성자 정보는 이 연습 저장소에만 저장되며 원격 전송은 없다.work=$(mktemp -d) && cd "$work" || exit 1git init -qgit config user.name 'Demo'git config user.email 'demo@example.invalid'printf 'first\n' > ..

순이익은 흑자인데, 영업현금흐름은 왜 마이너스일까?

순이익이 흑자여도 영업현금흐름은 마이너스일 수 있습니다. 제품을 팔아 이익을 기록한 날과 판매대금을 받은 날이 다르기 때문입니다. 돈을 받기 전에 재료비와 급여를 지급해야 한다면, 장부에는 이익이 남아도 현금은 줄어듭니다.실적을 볼 때는 순이익 옆에 영업활동 현금흐름을 놓고, 둘 사이의 차이가 어디서 생겼는지 확인해 볼 만합니다. 흑자라는 이유만으로 자금 사정까지 좋다고 판단하기는 어렵습니다.20억 원을 벌었는데 현금은 40억 원 줄었다면다음은 실제 회사가 아닌 단순한 가정입니다. 한 회사가 120억 원어치 제품을 팔았지만 이 기간에 받은 대금은 60억 원입니다. 팔린 제품의 원가는 90억 원이고, 아직 팔지 않은 재고도 30억 원어치 추가로 사 두었습니다. 총 120억 원의 재고 매입대금 중 100억 ..

SQL로 두 목록을 합쳤는데 행이 줄었다면: UNION ALL 확인하기

각각 조회하면 2건씩 나오는데 두 결과를 합치니 2건만 남는 경우가 있다. 집계 화면이라면 원본 데이터가 누락됐다고 의심하기 쉽다. 이때 쿼리 사이에 UNION을 썼는지 먼저 확인해 보자. UNION은 결과를 이어 붙이면서 중복 행도 제거한다.같은 값과 같은 사건은 다르다아래는 서로 다른 두 수집원에서 얻은 가상의 이벤트 기록이다. 새 실습용 DB에서만 실행한다. 실제 운영 테이블이나 사용자 로그가 아니다.CREATE TABLE events_a (event_id INTEGER PRIMARY KEY, kind TEXT NOT NULL);CREATE TABLE events_b (event_id INTEGER PRIMARY KEY, kind TEXT NOT NULL);INSERT INTO events_a VA..

미국주식 스톱로스, 설정한 가격보다 싸게 팔리는 이유

스톱로스를 95달러에 걸어 두었는데 88달러에 팔렸다면, 설정한 가격과 체결 가격을 먼저 나눠 봐야 합니다. 미국주식의 일반적인 매도 스톱 주문은 조건에 도달하면 시장가 주문으로 바뀝니다. 95달러는 주문을 작동시키는 가격이고, 실제로 받는 가격은 그때의 거래 가능한 물량에 따라 달라집니다.그래서 ‘매수가보다 5% 아래에 스톱을 걸었으니 최대 손실도 5%’라고 계산하면 문제가 생깁니다. 주문이 정상적으로 작동해도 예상보다 큰 손실이 날 수 있습니다.가격이 건너뛰면 손절선도 건너뛸 수 있습니다장 마감 뒤 악재가 나오거나 짧은 시간에 매수호가가 사라지면 가격이 큰 폭으로 벌어질 수 있습니다. 유효한 거래 시간에 스톱 조건이 충족돼도 95달러에 사 줄 상대가 남아 있다는 보장은 없습니다. SEC와 FINRA ..

Python 환경변수에 false를 넣었는데 기능이 켜지는 이유

환경변수에는 false라고 적었는데 기능이 켜진다면, 값을 읽은 뒤 bool()로 감싸고 있는지 확인해 보세요. Python의 bool()은 문자열에 적힌 참·거짓을 해석하지 않습니다. 문자열이 비어 있는지를 판단합니다.문자열 "false"는 False가 아닙니다다음은 실제 서비스 설정이 아닌 재현용 예제입니다.print(bool("false")) # Trueprint(bool("0")) # Trueprint(bool("")) # Falseprint(bool(" ")) # True"false"와 "0"은 모두 길이가 0보다 큰 문자열입니다. if raw:로 조건을 써도 같은 문제가 생깁니다. bool(os.getenv("DEMO_FEATURE_ENABLED", "false"..

반응형