<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>트레일링 스탑 보관 - 하우인포-IT·테크</title>
	<atom:link href="https://howinfo.kr/tag/%ed%8a%b8%eb%a0%88%ec%9d%bc%eb%a7%81-%ec%8a%a4%ed%83%91/feed/" rel="self" type="application/rss+xml" />
	<link>https://howinfo.kr/tag/트레일링-스탑/</link>
	<description>IT·AI 자동화 &#38; 인프라 전문 블로그 (하우인포)</description>
	<lastBuildDate>Wed, 25 Feb 2026 05:28:39 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://howinfo.kr/wp-content/uploads/2026/02/cropped-ChatGPT-Image-2026년-2월-12일-오후-05_39_40-32x32.png</url>
	<title>트레일링 스탑 보관 - 하우인포-IT·테크</title>
	<link>https://howinfo.kr/tag/트레일링-스탑/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>오렌지파이5로 주식·ETF 트레일링 스탑 알림 시스템 만들기</title>
		<link>https://howinfo.kr/%ec%98%a4%eb%a0%8c%ec%a7%80%ed%8c%8c%ec%9d%b45%eb%a1%9c-%ec%a3%bc%ec%8b%9d%c2%b7etf-%ed%8a%b8%eb%a0%88%ec%9d%bc%eb%a7%81-%ec%8a%a4%ed%83%91-%ec%95%8c%eb%a6%bc-%ec%8b%9c%ec%8a%a4%ed%85%9c-%eb%a7%8c/</link>
					<comments>https://howinfo.kr/%ec%98%a4%eb%a0%8c%ec%a7%80%ed%8c%8c%ec%9d%b45%eb%a1%9c-%ec%a3%bc%ec%8b%9d%c2%b7etf-%ed%8a%b8%eb%a0%88%ec%9d%bc%eb%a7%81-%ec%8a%a4%ed%83%91-%ec%95%8c%eb%a6%bc-%ec%8b%9c%ec%8a%a4%ed%85%9c-%eb%a7%8c/#respond</comments>
		
		<dc:creator><![CDATA[hong]]></dc:creator>
		<pubDate>Wed, 25 Feb 2026 02:53:59 +0000</pubDate>
				<category><![CDATA[개발·코딩]]></category>
		<category><![CDATA[etf 자동화]]></category>
		<category><![CDATA[Synology chat webhook]]></category>
		<category><![CDATA[Trailing stop]]></category>
		<category><![CDATA[시놀로지 챗 웹훅]]></category>
		<category><![CDATA[알림봇]]></category>
		<category><![CDATA[오렌지파이5]]></category>
		<category><![CDATA[주식 자동화]]></category>
		<category><![CDATA[주식알림시스템]]></category>
		<category><![CDATA[트레일링 스탑]]></category>
		<guid isPermaLink="false">https://howinfo.kr/?p=2098</guid>

					<description><![CDATA[<p>(Synology Chat 웹훅 + 종목별 트레일링% 설정 + 일일 요약 포함) 주식을 하다 보면 이런 생각이 듭니다. “최고 수익에서 10%만...</p>
<p>게시물 <a href="https://howinfo.kr/%ec%98%a4%eb%a0%8c%ec%a7%80%ed%8c%8c%ec%9d%b45%eb%a1%9c-%ec%a3%bc%ec%8b%9d%c2%b7etf-%ed%8a%b8%eb%a0%88%ec%9d%bc%eb%a7%81-%ec%8a%a4%ed%83%91-%ec%95%8c%eb%a6%bc-%ec%8b%9c%ec%8a%a4%ed%85%9c-%eb%a7%8c/">오렌지파이5로 주식·ETF 트레일링 스탑 알림 시스템 만들기</a>이 <a href="https://howinfo.kr">하우인포-IT·테크</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">(Synology Chat 웹훅 + 종목별 트레일링% 설정 + 일일 요약 포함)</h3>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">주식을 하다 보면 이런 생각이 듭니다.</h1>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>“최고 수익에서 10%만 빠지면 정리하고 싶은데…<br>내가 계속 보고 있을 수는 없잖아?”</p>
</blockquote>



<p>그래서 오렌지파이5에 <strong>상시 감시용 트레일링 알림 시스템</strong>을 만들었습니다.</p>



<p>✔ 일반주식 + ETF 모두 가능<br>✔ 종목별로 트레일링 % 다르게 설정<br>✔ 장중에만 매도 알림<br>✔ 장마감 후 하루 1번 요약<br>✔ 매도 알림 발생 시 자동 감시 해제</p>



<p>이 글에서는 <strong>실제 운영 가능한 코드 구조</strong>를 정리합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">🧠 시스템 구조</h1>



<pre class="wp-block-preformatted">positions.csv   → 보유 종목 관리<br>config.json     → 시스템 설정<br>state.json      → 종목별 최고 수익(peak) 저장<br>main.py         → 전체 로직 실행</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">📊 핵심 로직 (트레일링 스탑)</h1>



<h3 class="wp-block-heading">1️⃣ 기본 계산</h3>



<pre class="wp-block-preformatted">entry_value   = 매수수량 × 매수가<br>current_value = 매수수량 × 현재가<br>peak_value    = max(기존 peak_value, current_value)</pre>



<h3 class="wp-block-heading">2️⃣ 트레일링 기준선</h3>



<pre class="wp-block-preformatted">stop_value = peak_value × (1 - trailing_pct)</pre>



<h3 class="wp-block-heading">3️⃣ 매도 알림 조건</h3>



<pre class="wp-block-preformatted">수익 구간에서만 적용<br>current_value &lt;= stop_value 이면 알림</pre>



<p>✔ 계속 오르면 peak가 올라감<br>✔ 기준선도 같이 올라감<br>✔ 최고점 대비 n% 하락 시 알림</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">🗂 1️⃣ 보유 종목 파일 (positions.csv)</h1>



<pre class="wp-block-preformatted">code,name,market,qty,buy_price,trailing_pct,active<br>005930,삼성전자,KS,10,70000,0.10,1<br>069500,KODEX 200,KS,20,35000,0.08,1<br>035420,NAVER,KS,3,200000,0.12,1</pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>컬럼</th><th>설명</th></tr></thead><tbody><tr><td>code</td><td>6자리 종목코드</td></tr><tr><td>market</td><td>KS(코스피/ETF), KQ(코스닥)</td></tr><tr><td>qty</td><td>수량</td></tr><tr><td>buy_price</td><td>매수가</td></tr><tr><td>trailing_pct</td><td>종목별 트레일링 비율</td></tr><tr><td>active</td><td>1=감시, 0=감시중지</td></tr></tbody></table></figure>



<p>✔ 매도 알림 발생 시 active=0 자동 변경</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">⚙ 2️⃣ 설정 파일 (config.json)</h1>



<pre class="wp-block-preformatted">{<br>  "interval_minutes": 30,<br>  "default_trailing_pct": 0.10,<br>  "synology_chat_webhook_url": "웹훅URL",  "market_open": "09:00",<br>  "market_close": "15:30",  "daily_summary_time": "15:35",  "auto_disable_on_alert": true<br>}</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">🖥 3️⃣ 오렌지파이5 설치</h1>



<pre class="wp-block-preformatted">python3 -m pip install --upgrade pip<br>python3 -m pip install yfinance requests</pre>



<p>✔ ARM 환경에서 가장 안정적<br>✔ FinanceDataReader 대신 yfinance 사용</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">🧾 4️⃣ 전체 실행 코드 (주석 상세 버전)</h1>



<p>아래는 핵심 구조가 잘 보이도록 정리한 “설명형 소스”입니다.</p>



<pre class="wp-block-preformatted">"""<br>OrangePi5 트레일링 스탑 알림 시스템<br>- 주식 + ETF 지원<br>- 종목별 trailing_pct 적용<br>- 장중만 매도 알림<br>- 하루 1회 요약<br>- 매도 발생 시 active=0 자동 변경<br>"""import os<br>import json<br>import time<br>import csv<br>from datetime import datetime, timedelta, time as dtime<br>import requests<br>import yfinance as yf# -------------------------<br># 기본 경로 설정<br># -------------------------<br>BASE = os.path.dirname(os.path.abspath(__file__))<br>CONFIG_PATH = os.path.join(BASE, "config.json")<br>POSITIONS_PATH = os.path.join(BASE, "positions.csv")<br>STATE_PATH = os.path.join(BASE, "state.json")# -------------------------<br># 유틸 함수<br># -------------------------<br>def log(msg):<br>    print(f"[{datetime.now()}] {msg}")def fmt(x):<br>    return f"{x:,.0f}"def parse_hhmm(s):<br>    h, m = s.split(":")<br>    return dtime(int(h), int(m))# -------------------------<br># Synology Chat 알림<br># -------------------------<br>def send_chat(url, text):<br>    payload = json.dumps({"text": text}, ensure_ascii=False)<br>    requests.post(url, data={"payload": payload})# -------------------------<br># 가격 조회 (yfinance)<br># -------------------------<br>def get_price(code, market):<br>    ticker = f"{code}.{market}"<br>    hist = yf.Ticker(ticker).history(period="7d")<br>    return float(hist["Close"].iloc[-1])# -------------------------<br># 메인 실행<br># -------------------------<br>def main():<br>    config = json.load(open(CONFIG_PATH))<br>    state = json.load(open(STATE_PATH)) if os.path.exists(STATE_PATH) else {}    open_t = parse_hhmm(config["market_open"])<br>    close_t = parse_hhmm(config["market_close"])<br>    summary_t = parse_hhmm(config["daily_summary_time"])    while True:<br>        now = datetime.now()        # positions 읽기<br>        positions = list(csv.DictReader(open(POSITIONS_PATH, encoding="utf-8-sig")))<br>        positions = [p for p in positions if p.get("active","1") == "1"]        total_entry = total_current = total_peak = 0<br>        rows = []        for p in positions:<br>            code = p["code"]<br>            market = p.get("market","KS")<br>            qty = float(p["qty"])<br>            buy = float(p["buy_price"])<br>            trailing = float(p.get("trailing_pct") or config["default_trailing_pct"])            price = get_price(code, market)            entry = qty * buy<br>            current = qty * price            peak = state.get(code, {}).get("peak", entry)<br>            peak = max(peak, current)            state.setdefault(code, {})["peak"] = peak            # 트레일링 조건<br>            if open_t &lt;= now.time() &lt;= close_t:<br>                stop = peak * (1 - trailing)<br>                if current &lt;= stop:<br>                    send_chat(config["synology_chat_webhook_url"],<br>                              f"[매도 알림] {p['name']} 최고대비 {int(trailing*100)}% 하락")<br>                    if config["auto_disable_on_alert"]:<br>                        p["active"] = "0"            total_entry += entry<br>            total_current += current<br>            total_peak += peak            rows.append((p["name"], (current-entry)/entry*100))        # 하루 1회 요약<br>        if now.time() &gt;= summary_t:<br>            if state.get("summary_date") != now.strftime("%Y-%m-%d"):<br>                profit = total_current - total_entry<br>                send_chat(config["synology_chat_webhook_url"],<br>                          f"[일일 요약] 총 손익 {fmt(profit)}원")<br>                state["summary_date"] = now.strftime("%Y-%m-%d")        json.dump(state, open(STATE_PATH,"w"), indent=2)        log("루프 완료. 다음 실행 대기...")<br>        time.sleep(config["interval_minutes"]*60)if __name__ == "__main__":<br>    main()</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">📈 실행 중 로그 예시</h1>



<pre class="wp-block-preformatted">[2026-02-25 10:00] 가격 조회 시작<br>[2026-02-25 10:00] 삼성전자 peak 갱신<br>[2026-02-25 10:00] 트레일링 체크 완료<br>[2026-02-25 10:00] 루프 완료. 다음 실행 대기...</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">📌 운영하면서 느낀 점</h1>



<ul class="wp-block-list">
<li>지연 시세 기반이라 실시간 체결가 기반은 아님</li>



<li>그러나 구조 테스트 및 자동 감시 시스템에는 충분</li>



<li>실시간으로 확장하려면 가격 조회 부분만 API로 교체하면 됨</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">🚀 다음 확장 방향</h1>



<ul class="wp-block-list">
<li>증권사 API 연동</li>



<li>텔레그램/카카오톡 알림 추가</li>



<li>Streamlit 대시보드 추가</li>



<li>매수 전략 자동화</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">🧩 결론</h1>



<p>이 시스템은</p>



<p>✔ 오렌지파이5 같은 저전력 장비에 적합<br>✔ 구조가 단순해서 유지보수 쉬움<br>✔ 나중에 실시간 API로 확장 가능</p>



<p>입니다.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="855" height="433" src="https://howinfo.kr/wp-content/uploads/2026/02/sychat.png" alt="" class="wp-image-2102" srcset="https://howinfo.kr/wp-content/uploads/2026/02/sychat.png 855w, https://howinfo.kr/wp-content/uploads/2026/02/sychat-300x152.png 300w, https://howinfo.kr/wp-content/uploads/2026/02/sychat-768x389.png 768w" sizes="(max-width: 855px) 100vw, 855px" /></figure>
<p>게시물 <a href="https://howinfo.kr/%ec%98%a4%eb%a0%8c%ec%a7%80%ed%8c%8c%ec%9d%b45%eb%a1%9c-%ec%a3%bc%ec%8b%9d%c2%b7etf-%ed%8a%b8%eb%a0%88%ec%9d%bc%eb%a7%81-%ec%8a%a4%ed%83%91-%ec%95%8c%eb%a6%bc-%ec%8b%9c%ec%8a%a4%ed%85%9c-%eb%a7%8c/">오렌지파이5로 주식·ETF 트레일링 스탑 알림 시스템 만들기</a>이 <a href="https://howinfo.kr">하우인포-IT·테크</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://howinfo.kr/%ec%98%a4%eb%a0%8c%ec%a7%80%ed%8c%8c%ec%9d%b45%eb%a1%9c-%ec%a3%bc%ec%8b%9d%c2%b7etf-%ed%8a%b8%eb%a0%88%ec%9d%bc%eb%a7%81-%ec%8a%a4%ed%83%91-%ec%95%8c%eb%a6%bc-%ec%8b%9c%ec%8a%a4%ed%85%9c-%eb%a7%8c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
