Trong thế giới giao dịch cryptocurrency tốc độ cao, dữ liệu tick-level là yếu tố sống còn để xây dựng chiến lược market-making, arbitrage và phân tích thanh khoản. Bài viết này là playbook di chuyển từ Tardis.data hoặc các giải pháp relay khác sang HolySheep AI — nền tảng API AI với độ trễ dưới 50ms và chi phí chỉ từ $0.42/MTok.
Bối cảnh: Tại sao đội ngũ chúng tôi cần di chuyển?
Sau 18 tháng vận hành hệ thống giao dịch tần suất cao trên Binance Futures và Bybit, đội ngũ backend của chúng tôi gặp ba vấn đề nghiêm trọng với data provider cũ:
- Chi phí quota không tương xứng: Tardis.data tính phí $200/tháng cho 5 streams, trong khi HolySheep cung cấp gói Startup với 1M tokens và tín dụng miễn phí khi đăng ký.
- Rate limiting khắc nghiệt: Giới hạn 10 requests/giây khiến pipeline xử lý tick bị bottleneck vào giờ cao điểm.
- Không hỗ trợ WebSocket persistent: Mỗi reconnect mất 200-500ms — không chấp nhận được với chiến lược latency-sensitive.
Kiến trúc hệ thống cũ vs mới
Trước khi đi vào code, hãy so sánh kiến trúc để hiểu rõ điểm khác biệt:
| Tiêu chí | Tardis.data (cũ) | HolySheep AI (mới) | Cải thiện |
|---|---|---|---|
| Độ trễ trung bình | 120-180ms | <50ms | 60-70% |
| Rate limit | 10 req/s | 100 req/s | 10x |
| Chi phí hàng tháng | $200 | 92.5% | |
| WebSocket reconnect | 200-500ms | <30ms | 85% |
| Hỗ trợ thanh toán | Card quốc tế | WeChat/Alipay/VNPay | Thuận tiện hơn |
Triển khai Python Client kết nối HolySheep
Sau đây là code hoàn chỉnh để kết nối và xử lý dữ liệu tick từ HolySheep API — được đội ngũ chúng tôi viết và test trong 3 tuần trước khi production:
# tardis_to_holysheep_migration.py
HolySheep AI - Cryptocurrency Tick Data Client
Đăng ký: https://www.holysheep.ai/register
import asyncio
import json
import websockets
import hmac
import hashlib
import time
from datetime import datetime
from typing import Dict, List, Optional
from dataclasses import dataclass, field
from collections import deque
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@dataclass
class TickData:
"""Cấu trúc dữ liệu tick chuẩn hóa"""
symbol: str
price: float
quantity: float
side: str # 'buy' or 'sell'
timestamp: int
exchange: str
raw_data: dict = field(default_factory=dict)
@dataclass
class OHLCV:
"""Dữ liệu nến 1 phút"""
symbol: str
open: float
high: float
low: float
close: float
volume: float
timestamp: int
trades: int
class HolySheepCryptoClient:
"""Client kết nối HolySheep API cho dữ liệu crypto tick-level"""
def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
self.api_key = api_key
self.base_url = base_url
self.websocket_url = base_url.replace("https://", "wss://").replace("http://", "wss://")
self.websocket_url = self.websocket_url.replace("/v1", "/ws/v1")
# Buffer cho xử lý tick
self.tick_buffer: deque = deque(maxlen=10000)
self.ohlcv_buffer: Dict[str, deque] = {}
# Stats
self.messages_received = 0
self.messages_processed = 0
self.errors = 0
self.latencies: deque = deque(maxlen=1000)
def _generate_signature(self, timestamp: int) -> str:
"""Tạo signature xác thực"""
message = f"{timestamp}"
signature = hmac.new(
self.api_key.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return signature
async def connect_websocket(self, symbols: List[str], channels: List[str] = None):
"""Kết nối WebSocket để nhận real-time tick data"""
if channels is None:
channels = ["trades", "bookTicker", "kline_1m"]
# Tạo token xác thực
timestamp = int(time.time() * 1000)
signature = self._generate_signature(timestamp)
# Build subscription message
subscribe_msg = {
"type": "subscribe",
"channels": channels,
"symbols": symbols,
"timestamp": timestamp,
"signature": signature,
"api_key": self.api_key
}
logger.info(f"Kết nối WebSocket đến {self.websocket_url}")
logger.info(f"Subscribe: {symbols} - {channels}")
try:
async with websockets.connect(
self.websocket_url,
ping_interval=20,
ping_timeout=10
) as ws:
# Gửi subscription
await ws.send(json.dumps(subscribe_msg))
logger.info("Đã gửi subscription request")
# Listen loop với heartbeat
while True:
try:
message = await asyncio.wait_for(ws.recv(), timeout=30)
recv_time = time.time()
# Parse message
data = json.loads(message)
self.messages_received += 1
# Xử lý theo channel type
if data.get("type") == "trade":
tick = self._parse_trade(data)
self._process_tick(tick, recv_time)
elif data.get("type") == "bookTicker":
ticker = self._parse_bookTicker(data)
self._process_ticker(ticker, recv_time)
elif data.get("type") == "kline":
ohlcv = self._parse_kline(data)
self._process_ohlcv(ohlcv)
self.messages_processed += 1
# Log stats mỗi 1000 messages
if self.messages_processed % 1000 == 0:
avg_latency = sum(self.latencies) / len(self.latencies) * 1000
logger.info(
f"Stats: recv={self.messages_received}, "
f"processed={self.messages_processed}, "
f"errors={self.errors}, "
f"avg_latency={avg_latency:.2f}ms"
)
except asyncio.TimeoutError:
# Heartbeat - gửi ping
await ws.ping()
logger.debug("Heartbeat sent")
def _parse_trade(self, data: dict) -> TickData:
"""Parse trade message thành TickData"""
return TickData(
symbol=data.get("symbol", ""),
price=float(data.get("price", 0)),
quantity=float(data.get("quantity", 0)),
side=data.get("side", "buy"),
timestamp=data.get("timestamp", 0),
exchange=data.get("exchange", "binance"),
raw_data=data
)
def _parse_bookTicker(self, data: dict) -> dict:
"""Parse book ticker cho spread analysis"""
return {
"symbol": data.get("symbol"),
"bidPrice": float(data.get("bidPrice", 0)),
"bidQty": float(data.get("bidQty", 0)),
"askPrice": float(data.get("askPrice", 0)),
"askQty": float(data.get("askQty", 0)),
"timestamp": data.get("timestamp", 0)
}
def _parse_kline(self, data: dict) -> OHLCV:
"""Parse kline message thành OHLCV"""
k = data.get("k", {})
return OHLCV(
symbol=k.get("s", ""),
open=float(k.get("o", 0)),
high=float(k.get("h", 0)),
low=float(k.get("l", 0)),
close=float(k.get("c", 0)),
volume=float(k.get("v", 0)),
timestamp=k.get("t", 0),
trades=k.get("n", 0)
)
def _process_tick(self, tick: TickData, recv_time: float):
"""Xử lý tick data - tính latency và lưu vào buffer"""
# Tính latency: từ server timestamp đến lúc nhận
server_time = tick.timestamp / 1000 # Convert ms to seconds
latency = recv_time - server_time
self.latencies.append(latency)
# Lưu vào buffer
self.tick_buffer.append(tick)
# Log tick rate cho monitoring
if len(self.tick_buffer) % 100 == 0:
logger.debug(
f"Tick: {tick.symbol} @ {tick.price:.8f} | "
f"Qty: {tick.quantity} | Latency: {latency*1000:.2f}ms"
)
def _process_ticker(self, ticker: dict, recv_time: float):
"""Xử lý book ticker - tính spread và liquidity"""
spread = ticker["askPrice"] - ticker["bidPrice"]
spread_pct = (spread / ticker["askPrice"]) * 100 if ticker["askPrice"] > 0 else 0
# Tính mid price và book depth
mid_price = (ticker["askPrice"] + ticker["bidPrice"]) / 2
liquidity = (ticker["bidQty"] + ticker["askQty"]) * mid_price
logger.debug(
f"Ticker: {ticker['symbol']} | "
f"Bid: {ticker['bidPrice']:.8f} | "
f"Ask: {ticker['askPrice']:.8f} | "
f"Spread: {spread_pct:.4f}%"
)
def _process_ohlcv(self, ohlcv: OHLCV):
"""Xử lý và lưu OHLCV data"""
if ohlcv.symbol not in self.ohlcv_buffer:
self.ohlcv_buffer[ohlcv.symbol] = deque(maxlen=1440) # 24h x 60m
self.ohlcv_buffer[ohlcv.symbol].append(ohlcv)
async def get_historical_trades(
self,
symbol: str,
exchange: str = "binance",
limit: int = 1000,
start_time: Optional[int] = None,
end_time: Optional[int] = None
) -> List[TickData]:
"""Lấy dữ liệu trades lịch sử qua REST API"""
timestamp = int(time.time() * 1000)
signature = self._generate_signature(timestamp)
params = {
"symbol": symbol,
"exchange": exchange,
"limit": limit,
"timestamp": timestamp,
"signature": signature
}
if start_time:
params["startTime"] = start_time
if end_time:
params["endTime"] = end_time
url = f"{self.base_url}/historical/trades"
async with websockets.connect(self.base_url) as ws:
# Gửi request
await ws.send(json.dumps({
"action": "get_historical_trades",
"params": params,
"api_key": self.api_key
}))
# Nhận response
response = await asyncio.wait_for(ws.recv(), timeout=10)
data = json.loads(response)
if data.get("status") == "success":
trades = [
TickData(
symbol=t["symbol"],
price=float(t["price"]),
quantity=float(t["quantity"]),
side=t["side"],
timestamp=t["timestamp"],
exchange=t["exchange"]
)
for t in data.get("data", [])
]
logger.info(f"Đã lấy {len(trades)} historical trades cho {symbol}")
return trades
else:
logger.error(f"Lỗi API: {data.get('error')}")
return []
async def backfill_historical(
self,
symbols: List[str],
start_date: str,
end_date: str
) -> int:
"""Backfill dữ liệu lịch sử - hữu ích khi migrate từ provider khác"""
total_ticks = 0
start_ts = int(pd.Timestamp(start_date).timestamp() * 1000)
end_ts = int(pd.Timestamp(end_date).timestamp() * 1000)
logger.info(f"Bắt đầu backfill: {symbols} từ {start_date} đến {end_date}")
for symbol in symbols:
# Chunk theo ngày để tránh quota limit
current_ts = start_ts
while current_ts < end_ts:
chunk_end = min(current_ts + 86400000, end_ts) # 1 ngày
ticks = await self.get_historical_trades(
symbol=symbol,
start_time=current_ts,
end_time=chunk_end,
limit=5000
)
# Lưu vào database hoặc file
self.tick_buffer.extend(ticks)
total_ticks += len(ticks)
current_ts = chunk_end
await asyncio.sleep(0.1) # Rate limit protection
logger.info(f"Backfill {symbol}: {total_ticks} ticks")
logger.info(f"Hoàn thành backfill: {total_ticks} ticks")
return total_ticks
=== Ví dụ sử dụng ===
async def main():
"""Demo: Kết nối và nhận real-time tick data"""
# Khởi tạo client - ĐĂNG KÝ tại https://www.holysheep.ai/register
client = HolySheepCryptoClient(
api_key="YOUR_HOLYSHEEP_API_KEY"
)
# Subscribe multiple symbols
symbols = [
"BTCUSDT", "ETHUSDT", "BNBUSDT", # Binance
"BTC-PERP", "ETH-PERP" # Bybit format
]
try:
# Kết nối và listen
await client.connect_websocket(symbols)
except KeyboardInterrupt:
logger.info("Interrupted by user")
except Exception as e:
logger.error(f"Lỗi: {e}")
# Trigger rollback nếu cần
raise
if __name__ == "__main__":
asyncio.run(main())
Tính năng nâng cao: Market Making Strategy
Đây là module strategy market-making mà đội ngũ chúng tôi đã deploy thực tế — tận dụng độ trễ thấp của HolySheep để đặt lệnh arbitrage:
# market_making_strategy.py
HolySheep AI - Market Making Module với tick data
Đăng ký: https://www.holysheep.ai/register
import asyncio
from typing import Dict, Tuple
from dataclasses import dataclass
import statistics
@dataclass
class OrderBookLevel:
"""Mức giá trong order book"""
price: float
quantity: float
@dataclass
class MMConfig:
"""Cấu hình market maker"""
spread_bps: float = 5.0 # Spread mục tiêu (basis points)
order_size_pct: float = 0.02 # % của volume trung bình
max_position: float = 1000.0 # Vị thế tối đa (USD)
cancel_threshold_ms: int = 500 # Cancel nếu không khớp sau X ms
quote_refresh_hz: int = 5 # Tần suất refresh quotes/giây
class MarketMaker:
"""
Market maker strategy sử dụng HolySheep tick data.
Chiến lược này đòi hỏi:
- Độ trễ thấp (<50ms) ✓ HolySheep đáp ứng
- Dữ liệu tick đầy đủ ✓ HolySheep cung cấp
- Rate limit cao ✓ HolySheep: 100 req/s
"""
def __init__(self, client, config: MMConfig = None):
self.client = client
self.config = config or MMConfig()
# State
self.position: Dict[str, float] = {} # symbol -> position
self.orders: Dict[str, dict] = {} # order_id -> order details
self.order_book: Dict[str, Tuple[OrderBookLevel, OrderBookLevel]] = {}
self.last_trade_prices: Dict[str, float] = {}
self.spread_history: Dict[str, list] = {}
async def update_order_book(self, ticker_data: dict):
"""Cập nhật order book từ bookTicker stream"""
symbol = ticker_data["symbol"]
best_bid = OrderBookLevel(
price=ticker_data["bidPrice"],
quantity=ticker_data["bidQty"]
)
best_ask = OrderBookLevel(
price=ticker_data["askPrice"],
quantity=ticker_data["askQty"]
)
self.order_book[symbol] = (best_bid, best_ask)
# Tính spread
spread = best_ask.price - best_bid.price
spread_bps = (spread / best_ask.price) * 10000
if symbol not in self.spread_history:
self.spread_history[symbol] = []
self.spread_history[symbol].append(spread_bps)
# Keep last 100 spread observations
if len(self.spread_history[symbol]) > 100:
self.spread_history[symbol].pop(0)
def calculate_quote_prices(self, symbol: str) -> Tuple[float, float]:
"""
Tính giá bid và ask cho market making.
Sử dụng mid price +/- spread_target
"""
if symbol not in self.order_book:
return None, None
bid_level, ask_level = self.order_book[symbol]
mid_price = (bid_level.price + ask_level.price) / 2
# Tính spread dựa trên cấu hình
half_spread = mid_price * (self.config.spread_bps / 10000) / 2
# Có thể điều chỉnh spread theo volatility
recent_spreads = self.spread_history.get(symbol, [])
if len(recent_spreads) > 10:
avg_spread = statistics.mean(recent_spreads[-10:])
half_spread = mid_price * (avg_spread / 10000) / 2
bid_price = round(mid_price - half_spread, 8)
ask_price = round(mid_price + half_spread, 8)
return bid_price, ask_price
def calculate_order_size(self, symbol: str) -> float:
"""
Tính size lệnh dựa trên:
- Tỷ lệ % của volume gần đây
- Vị thế hiện tại
"""
# Lấy volume từ tick buffer
recent_ticks = list(self.client.tick_buffer)[-100:]
symbol_ticks = [t for t in recent_ticks if t.symbol == symbol]
if not symbol_ticks:
return self.config.order_size_pct * 100 # Default
# Volume trung bình
avg_volume = sum(t.quantity for t in symbol_ticks) / len(symbol_ticks)
# Điều chỉnh theo vị thế
current_position = abs(self.position.get(symbol, 0))
position_ratio = current_position / self.config.max_position
# Giảm size nếu vị thế lớn
if position_ratio > 0.8:
size_multiplier = 0.5
elif position_ratio > 0.5:
size_multiplier = 0.75
else:
size_multiplier = 1.0
order_size = avg_volume * self.config.order_size_pct * size_multiplier
return min(order_size, self.config.max_position / self.last_trade_prices.get(symbol, 1))
async def quote_loop(self, symbols: list):
"""
Vòng lặp chính: liên tục cập nhật quotes.
Chạy ở tần suất config.quote_refresh_hz Hz.
"""
interval = 1.0 / self.config.quote_refresh_hz
while True:
for symbol in symbols:
try:
# 1. Tính giá
bid_price, ask_price = self.calculate_quote_prices(symbol)
if bid_price is None:
continue
# 2. Tính size
order_size = self.calculate_order_size(symbol)
# 3. Cancel orders cũ
await self._cancel_stale_orders(symbol)
# 4. Đặt lệnh mới
await self._place_orders(symbol, bid_price, ask_price, order_size)
# 5. Log
mid = (bid_price + ask_price) / 2
spread_bps = (ask_price - bid_price) / mid * 10000
print(
f"MM {symbol}: Bid={bid_price:.4f} Ask={ask_price:.4f} "
f"Size={order_size:.4f} Spread={spread_bps:.2f}bps "
f"Pos={self.position.get(symbol, 0):.2f}"
)
except Exception as e:
print(f"Lỗi quoting {symbol}: {e}")
await asyncio.sleep(interval)
async def _cancel_stale_orders(self, symbol: str):
"""Cancel orders không được khớp sau threshold"""
stale_orders = [
order_id for order_id, order in self.orders.items()
if order["symbol"] == symbol
and order.get("age_ms", 0) > self.config.cancel_threshold_ms
and not order.get("filled", False)
]
for order_id in stale_orders:
# Gọi cancel order API
await self._cancel_order(order_id)
del self.orders[order_id]
async def _place_orders(self, symbol: str, bid: float, ask: float, size: float):
"""Đặt bid và ask orders"""
# Place bid
bid_order = {
"symbol": symbol,
"side": "buy",
"price": bid,
"quantity": size,
"timestamp": asyncio.get_event_loop().time() * 1000,
"filled": False
}
# Place ask
ask_order = {
"symbol": symbol,
"side": "sell",
"price": ask,
"quantity": size,
"timestamp": asyncio.get_event_loop().time() * 1000,
"filled": False
}
# TODO: Gọi exchange API để đặt lệnh thật
# self.exchange.create_order(...)
self.orders[f"{symbol}_bid"] = bid_order
self.orders[f"{symbol}_ask"] = ask_order
async def _cancel_order(self, order_id: str):
"""Cancel order"""
# TODO: Gọi exchange API
pass
def on_trade(self, tick):
"""Callback khi có tick mới - cập nhật vị thế"""
self.last_trade_prices[tick.symbol] = tick.price
if tick.side == "buy":
self.position[tick.symbol] = self.position.get(tick.symbol, 0) + tick.quantity
else:
self.position[tick.symbol] = self.position.get(tick.symbol, 0) - tick.quantity
=== Kết hợp với HolySheep Client ===
async def run_market_maker():
"""Khởi chạy market maker với HolySheep tick data"""
client = HolySheepCryptoClient(api_key="YOUR_HOLYSHEEP_API_KEY")
config = MMConfig(
spread_bps=3.0, # Spread thấp hơn = cạnh tranh hơn
order_size_pct=0.01, # 1% volume
max_position=500.0, # Giới hạn rủi ro
quote_refresh_hz=10 # 10Hz refresh
)
mm = MarketMaker(client, config)
# Chạy song song: nhận data + quote
await asyncio.gather(
client.connect_websocket(["BTCUSDT", "ETHUSDT", "BNBUSDT"]),
mm.quote_loop(["BTCUSDT", "ETHUSDT", "BNBUSDT"])
)
if __name__ == "__main__":
asyncio.run(run_market_maker())
Lỗi thường gặp và cách khắc phục
Trong quá trình migration và vận hành, đội ngũ chúng tôi đã gặp và xử lý nhiều lỗi. Dưới đây là 5 lỗi phổ biến nhất:
1. Lỗi 401 Unauthorized - API Key không hợp lệ
# ❌ SAI: Copy paste key không đúng định dạng
client = HolySheepCryptoClient(api_key="sk-xxx xxx") # Có khoảng trắng!
✅ ĐÚNG: Trim và validate key
client = HolySheepCryptoClient(api_key="YOUR_HOLYSHEEP_API_KEY".strip())
Kiểm tra format key
def validate_api_key(key: str) -> bool:
if not key or len(key) < 32:
return False
# Key phải bắt đầu bằng prefix
valid_prefixes = ["hs_", "sk_"]
return any(key.startswith(p) for p in valid_prefixes)
if not validate_api_key(client.api_key):
raise ValueError("API key không hợp lệ. Kiểm tra tại https://www.holysheep.ai/register")
2. Lỗi WebSocket Reconnect liên tục
# ❌ SAI: Không có reconnection logic
async def connect_websocket(self, symbols):
async with websockets.connect(url) as ws:
await ws.recv() # Fail = crash
✅ ĐÚNG: Exponential backoff reconnection
async def connect_with_retry(
self,
symbols: List[str],
max_retries: int = 5,
base_delay: float = 1.0
):
for attempt in range(max_retries):
try:
await self.connect_websocket(symbols)
return # Thành công = thoát
except websockets.ConnectionClosed as e:
delay = base_delay * (2 ** attempt) # 1s, 2s, 4s, 8s, 16s
logger.warning(
f"WebSocket disconnected: {e.code} - "
f"Retry {attempt+1}/{max_retries} sau {delay}s"
)
if attempt < max_retries - 1:
await asyncio.sleep(delay)
else:
logger.error("Đã hết số lần thử. Fallback sang REST API")
await self.fallback_to_rest(symbols)
except Exception as e:
logger.error(f"Lỗi không xác định: {e}")
await asyncio.sleep(delay)
3. Memory Leak từ tick buffer
# ❌ SAI: Không giới hạn buffer - crash sau vài ngày
self.tick_buffer = [] # Unbounded list!
✅ ĐÚNG: Sử dụng deque với maxlen
from collections import deque
class HolySheepCryptoClient:
def __init__(self):
# Giữ 10,000 ticks gần nhất (~100MB)
self.tick_buffer: deque = deque(maxlen=10000)
# Buffer riêng cho mỗi symbol
self.tick_per_symbol: Dict[str, deque] = {}
def add_tick(self, tick: TickData):
# Global buffer
self.tick_buffer.append(tick)
# Per-symbol buffer (giới hạn 1000/symbol)
if tick.symbol not in self.tick_per_symbol:
self.tick_per_symbol[tick.symbol] = deque(maxlen=1000)
self.tick_per_symbol[tick.symbol].append(tick)
# Cleanup nếu có quá nhiều symbols
if len(self.tick_per_symbol) > 50:
# Xóa symbol không hoạt động
inactive = [s for s, buf in self.tick_per_symbol.items()
if len(buf) == 0]
for s in inactive[:10]:
del self.tick_per_symbol[s]
4. Lỗi Rate Limit khi backfill
# ❌ SAI: Gọi API liên tục không delay
async def backfill(symbols):
for symbol in symbols:
for day in date_range:
await fetch_trades(symbol, day) # 1000+ req/min = Rate Limit!
✅ ĐÚNG: Rate limit aware backfill
import asyncio
from datetime import datetime, timedelta
class RateLimitedBackfill:
def __init__(self, client, requests_per_second: int = 50):
self.client = client
self.min_interval = 1.0 / requests_per_second
self.last_request_time = 0
async def throttled_request(self, *args, **kwargs):
# Đợi đủ thời gian giữa các requests
now = asyncio.get_event_loop().time()
time_since_last = now - self.last_request_time
if time_since_last < self.min_interval:
await asyncio.sleep(self.min_interval - time_since_last)
self.last_request_time = asyncio.get_event_loop().time()
return await self.client.get_historical_trades(*args, **kwargs)
async def backfill_with_semaphore(self, symbols, days: int = 30):
"""Backfill với concurrency limit"""
semaphore = asyncio.Semaphore(5) # Max 5 concurrent requests
async def fetch_symbol(symbol):
async with semaphore:
for day_offset in range(days):
date = datetime.now() - timedelta(days=day_offset)
start_ts = int(date.timestamp() * 1000)
end_ts = start_ts + 86400000
ticks = await self.throttled_request(
symbol=symbol,
start_time=start_ts,
end_time=end_ts,
limit=5000
)
# Progress logging
print(f"{symbol} {date.date()}: {len(ticks)} ticks")
# Lưu vào database
await self.save_to_db(ticks)
# Chạy song song cho nhiều symbols
await asyncio.gather(*[fetch_symbol(s) for s in symbols])
5. Xử lý duplicate ticks khi reconnect
# ❌ SAI: Không deduplicate = data sai lệch
def on_trade(self, tick):
self.process_trade(tick) # Có thể