เวลาเพี้ยน 3 ชั่วโมง เพราะฟังก์ชันของ MT5 Python API ใช้ timezone ต่างกัน
ไลบรารีตัวเดียวกัน ต่อ terminal ตัวเดียวกัน แต่ฟังก์ชันหนึ่งรับเวลาเซิร์ฟเวอร์แล้วคืน UTC อีกฟังก์ชันคืนเวลาเซิร์ฟเวอร์ทั้งที่ชื่อคอลัมน์เหมือนกันทุกตัว ถ้าไม่วัดทีละฟังก์ชัน ข้อมูลจะเพี้ยนสามชั่วโมงแบบเลือกที่ ซึ่งหายากกว่าเพี้ยนทั้งระบบมาก
สรุปใน 1 นาที
- อาการ/ปัญหา
- ข้อมูลที่เก็บผ่าน MT5 Python API เวลาเพี้ยน 3 ชั่วโมงเป็นบางคอลัมน์
- ใครควรอ่าน
- คนเก็บข้อมูลราคาด้วย MT5 Python API
- ทางแก้แบบสั้น
- แต่ละฟังก์ชันรับและคืนเวลาคนละเขต ให้พิสูจน์ทีละฟังก์ชันโดยยิงช่วงเดียวกันสองครั้ง จดเป็นตาราง 8 ฟังก์ชัน และใส่ด่านตรวจเวลาในโปรแกรม
พอดีผมทำระบบเก็บข้อมูลจาก terminal ของ MetaTrader 5 ผ่านแพ็กเกจ Python ของมัน เอาไว้ทำคลังข้อมูลสำหรับวิเคราะห์ย้อนหลัง ช่วงแรกทุกอย่างดูปกติ จนวันหนึ่งผมเอาแท่งข้อมูลรายนาทีไปวางเทียบกับ tick ดิบของช่วงเวลาเดียวกัน แล้วพบว่าแท่งนำหน้า tick อยู่สามชั่วโมงพอดี ไม่มี error ไม่มีคำเตือน ตัวเลขทุกตัวเป็น unix timestamp หน้าตาปกติ ที่ผิดคือมันเป็นเวลาคนละเขตกัน ทั้งที่มาจากไลบรารีตัวเดียวกันและ terminal ตัวเดียวกัน
ผมเข้าใจมาตลอดว่า API ชุดนี้ใช้เวลาเขตเดียวทั้งชุด ถ้าไม่ UTC ทั้งหมดก็เวลาเซิร์ฟเวอร์ทั้งหมด ความเข้าใจนี้ผิดทั้งสองทาง ของจริงคือปนกัน และปนกันถึงระดับที่ฟังก์ชันเดียวรับเวลาแบบหนึ่งแล้วคืนอีกแบบหนึ่ง ชื่อโบรกเกอร์ ชื่อเซิร์ฟเวอร์ และชื่อสัญลักษณ์ในบทความนี้ผมเปลี่ยนเป็นโบรก A โบรก B กับสัญลักษณ์ A ทั้งหมด ส่วนตารางและตัวเลขคือของที่วัดได้จริง บทความนี้พูดเรื่องเวลาของข้อมูลอย่างเดียว
อาการ: เพี้ยนเป็นบางคอลัมน์ ไม่ได้เพี้ยนทั้งระบบ
ถ้าเวลาเพี้ยนทั้งระบบเท่ากันหมด มันจะไม่ค่อยมีใครเดือดร้อน เพราะทุกอย่างยังเรียงลำดับถูกและเทียบกันเองได้ ที่ทำให้งานพังคือเพี้ยนเป็นบางแหล่ง เซิร์ฟเวอร์ของโบรก A ตั้งนาฬิกาเป็นเวลาท้องถิ่นที่มีการปรับเวลาตามฤดู ซึ่งเร็วกว่า UTC อยู่ 2 ชั่วโมงในฤดูหนาวและ 3 ชั่วโมงในฤดูร้อน ตอนที่ผมเจอปัญหาเป็นช่วงฤดูร้อน ตัวเลขที่โผล่ซ้ำไปซ้ำมาเลยเป็น 10800 วินาที
อาการที่เห็นมีสี่แบบ และตอนแรกผมมองว่าเป็นสี่เรื่องที่ไม่เกี่ยวกัน
| อาการ | สิ่งที่เห็น |
|---|---|
| แท่งวินาทีที่ปั้นเองจาก tick ไม่ตรงกับแท่งนาทีจาก API | ห่างกัน 3 ชั่วโมง |
| อายุของรายการที่เปิดค้างอยู่ | ติดลบ -10800 วินาที |
| ค้นประวัติรายการช่วง 30 นาทีล่าสุด | ได้ลิสต์ว่าง ทั้งที่รู้ว่ามี |
| เวลาเปิดของแท่งนาทีล่าสุด | อยู่ในอนาคต 3 ชั่วโมง |
เลขสามชั่วโมงที่โผล่ทุกแถวคือสิ่งที่ทำให้ผมหยุดแก้ทีละจุด แล้วกลับไปตั้งคำถามใหม่ว่าฟังก์ชันไหนพูดเวลาเขตไหนกันแน่ เรื่องเวลาเพี้ยนแบบเงียบในชั้นแอปกับฐานข้อมูลผมเคยเขียนไว้แล้วใน ตอนแอปเป็น UTC แต่คนคิดเป็นเวลาไทย เรื่องนี้เป็นญาติกัน แต่เกิดลึกลงไปอีกชั้นหนึ่ง คือชั้นของไลบรารีที่ดึงข้อมูลมาตั้งแต่ต้นทาง
ตาราง 8 ฟังก์ชัน: เวลาขาเข้าและขาออกไม่เท่ากัน
ผมไล่วัดทีละฟังก์ชันกับ terminal ของโบรก A แล้วได้ตารางนี้ คอลัมน์ขาเข้าคือ datetime ที่เราส่งเข้าไปถูกตีความเป็นเวลาเขตไหน คอลัมน์ขาออกคือ timestamp ในผลลัพธ์เป็นเวลาเขตไหน
| ฟังก์ชัน | ขาเข้า | ขาออก | ต้องทำอะไร |
|---|---|---|---|
copy_ticks_from |
UTC | UTC | ใช้ได้เลย ห้ามลบ offset |
copy_ticks_range |
UTC | UTC | เหมือนตัวบน |
copy_rates_from_pos |
ไม่รับเวลา | SERVER | ลบ offset ออกจากคอลัมน์เวลา |
copy_rates_range |
SERVER | SERVER | บวก offset ขาเข้า ลบ offset ขาออก |
history_deals_get |
SERVER | UTC | บวก offset ขาเข้า ขาออกใช้ได้เลย |
history_orders_get |
SERVER | SERVER | ขาออกผมยังไม่ได้วัดเอง ใช้ตามที่คาดไว้ |
positions_get |
ไม่รับเวลา | SERVER | ลบ offset ออกจากเวลาเปิด |
symbol_info_tick |
ไม่รับเวลา | UTC | ใช้ได้เลย |
แถวที่ทำผมเสียเวลามากที่สุดคือ history_deals_get เพราะมันรับช่วงเวลาเป็นเวลาเซิร์ฟเวอร์ แต่เวลาในผลลัพธ์กลับเป็น UTC ถ้าเราแก้โดยคิดว่า "ฟังก์ชันนี้ใช้เวลาเซิร์ฟเวอร์" แล้วไปลบ offset ที่ขาออกด้วย ก็จะได้ของผิดอีกรอบในทิศตรงข้าม
ทุกฟังก์ชันคืนคอลัมน์ชื่อ time เป็นจำนวนเต็มวินาทีเหมือนกันหมด ไม่มี field ไหนบอกว่าเป็น UTC หรือเวลาเซิร์ฟเวอร์ และการเอาไปเข้า datetime.fromtimestamp(x, tz=timezone.utc) ก็ไม่ได้ทำให้มันกลายเป็น UTC ขึ้นมา มันแค่ติดป้าย UTC ให้ตัวเลขที่อาจเป็นเวลาเซิร์ฟเวอร์อยู่ ป้ายผิดแบบนี้อันตรายกว่าไม่มีป้าย เพราะโค้ดชั้นถัดไปจะเชื่อป้าย
วิธีพิสูจน์: ยิงช่วงเดียวกันสองแบบ แล้วดูว่าแบบไหนได้ของครบ
ผมไม่อยากเชื่อเอกสารหรือกระทู้ไหนอีกแล้ว เลยใช้วิธีวัดตรง ๆ หลักคือฟังก์ชันที่รับช่วงเวลา ให้ถามช่วง "หนึ่งชั่วโมงล่าสุด" สองครั้ง ครั้งแรกส่งเป็น UTC ครั้งที่สองส่งเป็นเวลาเซิร์ฟเวอร์ แล้วเทียบผล
from datetime import datetime, timedelta, timezone
import MetaTrader5 as mt5
OFFSET_SEC = 10800 # เซิร์ฟเวอร์ของโบรก A ช่วงฤดูร้อน = UTC+3
mt5.initialize() # terminal ต้องเปิดและล็อกอินอยู่แล้ว
now_utc = datetime.now(timezone.utc)
srv_now = now_utc + timedelta(seconds=OFFSET_SEC)
as_utc = mt5.history_deals_get(now_utc - timedelta(hours=1), now_utc)
as_srv = mt5.history_deals_get(srv_now - timedelta(hours=1), srv_now)
print('ส่งแบบ UTC :', len(as_utc or ())) # รอบที่ผมวัดได้ 16
print('ส่งแบบ SERVER:', len(as_srv or ())) # รอบที่ผมวัดได้ 26
รอบที่ผมวัด ส่งแบบ UTC ได้ 16 รายการ ส่งแบบเวลาเซิร์ฟเวอร์ได้ 26 รายการ ตัวที่ได้มากกว่าคือตัวที่ช่วงเวลาถูก เพราะถ้าฟังก์ชันตีความขาเข้าเป็นเวลาเซิร์ฟเวอร์ แล้วเราส่ง UTC เข้าไป ขอบบนของช่วงจะไปตกที่สามชั่วโมงก่อนหน้าปัจจุบัน รายการที่เกิดช่วงท้ายสุดเลยหลุดออกไปหมด
การนับจำนวนใช้ชี้ทางได้ แต่ถ้าจะให้แน่นกว่านั้น ให้ดูว่ารายการล่าสุดที่รู้แน่ว่าเพิ่งเกิดเมื่อไม่กี่นาทีก่อนอยู่ในชุดไหน ชุดที่มีมันคือชุดที่ตีความขาเข้าถูก ส่วนขาออกพิสูจน์แยกอีกขั้น คือเอาเวลาของรายการล่าสุดในผลลัพธ์มาเทียบกับนาฬิกา UTC ของเครื่อง ถ้าห่างกันไม่กี่วินาทีคือ UTC ถ้าห่างกันเป็นจำนวนชั่วโมงเต็มคือเวลาเซิร์ฟเวอร์
- เลือกฟังก์ชันทีละตัว อย่าวัดรวมแล้วเหมาว่าทั้งกลุ่มเหมือนกัน เพราะในกลุ่ม history เองก็ยังไม่เหมือนกัน
- ถ้าฟังก์ชันรับช่วงเวลา ให้ยิงช่วงเดียวกันสองแบบ คือ UTC กับ UTC บวก offset แล้วดูว่าแบบไหนได้รายการล่าสุดครบ
- เอา timestamp ตัวล่าสุดในผลลัพธ์ไปลบกับ
time.time()ของเครื่อง ถ้าได้ใกล้ศูนย์คือ UTC ถ้าได้ใกล้ 7200 หรือ 10800 คือเวลาเซิร์ฟเวอร์ - วัดตอนที่ข้อมูลกำลังวิ่งอยู่จริงเท่านั้น วัดตอนที่ต้นทางหยุดส่งจะได้ tick ค้างของวันก่อน แล้วส่วนต่างจะเป็นเลขอะไรก็ได้
- จดผลเป็นตารางแยกขาเข้ากับขาออก พร้อมวันที่วัดและโบรกที่วัด แล้วเก็บไว้ในโปรเจกต์ ไม่ใช่ในหัว
บั๊กสี่แบบที่มาจากความเข้าใจผิดสองทิศ
พอมีตารางแล้วกลับไปดูอาการสี่แบบข้างบน มันมาจากความเข้าใจผิดแค่สองทิศ ทิศแรกคือคิดว่าทุกอย่างเป็น UTC ทิศที่สองคือพอรู้ว่ามีเวลาเซิร์ฟเวอร์ ก็ไปลบ offset ให้ทุกอย่าง
คิดว่าทุกอย่างเป็น UTC
- เอาเวลาของแท่งนาทีไปใช้ตรง ๆ = ล่วงหน้า 3 ชั่วโมง
- เอาเวลาเปิดของรายการค้างมาลบกับ now แบบ UTC = อายุ -10800 วินาที
- ส่ง UTC เข้า history_deals_get = ได้ลิสต์ว่างหรือไม่ครบ
ลบ offset ให้ทุกอย่าง
- ลบ offset จาก tick ที่เป็น UTC อยู่แล้ว = ถอยหลัง 3 ชั่วโมง
- แท่งวินาทีที่ปั้นจาก tick เลยไม่ตรงกับแท่งนาทีที่แก้ถูกแล้ว
- ลบ offset จากขาออกของ history_deals_get ซ้ำอีกรอบ
ทางแก้ของผมคือเลิกให้โค้ดแต่ละจุดตัดสินใจเองว่าจะบวกหรือลบ แล้วรวมการแปลงทั้งหมดไว้ในโมดูลเดียว ทุกฟังก์ชันที่ออกจากโมดูลนี้คืน UTC เสมอ โค้ดส่วนอื่นห้ามแตะ offset อีก
# mt5_time.py — ทุกอย่างที่ออกจากไฟล์นี้เป็น UTC แล้ว ชั้นอื่นห้ามบวกลบ offset เอง
from datetime import datetime, timedelta, timezone
import MetaTrader5 as mt5
def rates_utc(symbol, tf, count, offset_sec):
rates = mt5.copy_rates_from_pos(symbol, tf, 0, count) # ขาออก SERVER
return [(int(r['time']) - offset_sec, r) for r in rates]
def ticks_utc(symbol, from_utc, count):
ticks = mt5.copy_ticks_from(symbol, from_utc, count, mt5.COPY_TICKS_ALL)
return [(int(t['time']), t) for t in ticks] # UTC อยู่แล้ว ไม่ลบ
def open_age_sec(pos, offset_sec):
opened = datetime.fromtimestamp(pos.time - offset_sec, tz=timezone.utc)
return (datetime.now(timezone.utc) - opened).total_seconds()
def deals_last(minutes, offset_sec):
srv_now = datetime.now(timezone.utc) + timedelta(seconds=offset_sec)
deals = mt5.history_deals_get(srv_now - timedelta(minutes=minutes), srv_now)
return [(datetime.fromtimestamp(d.time, tz=timezone.utc), d) for d in deals or ()]
ฟังก์ชันสุดท้ายคือตัวอย่างของแถวที่อันตรายที่สุดในตาราง ขาเข้าบวก offset แต่ขาออกไม่แตะเลย ถ้าไม่ได้เขียนรวมไว้ที่เดียว ผมมั่นใจว่าอีกสามเดือนจะมีคนมา "แก้ให้สม่ำเสมอ" แล้วพังอีกรอบ และคนคนนั้นน่าจะเป็นผมเอง
offset ที่วัดครั้งเดียวแล้วปัดเป็นชั่วโมง ใช้ไม่ได้เมื่อข้ามวันเปลี่ยนเวลา
ตัวเลข offset_sec ในโค้ดข้างบนมาจากไหนเป็นอีกเรื่องหนึ่งที่ผมพลาดซ้ำ เวอร์ชันแรกผมวัดครั้งเดียวตอนโปรแกรมเริ่มทำงาน โดยเอาเวลาของ tick ล่าสุดที่เป็นนาฬิกาเซิร์ฟเวอร์มาลบกับนาฬิกา UTC ของเครื่อง แล้วปัดเป็นชั่วโมงเต็ม
# เวอร์ชันแรก: วัดครั้งเดียวตอนเริ่ม แล้วใช้ค่านั้นตลอดอายุของ process
def detect_server_offset(symbol):
tick = mt5.symbol_info_tick(symbol)
utc_now = datetime.now(timezone.utc).timestamp()
return int(round((tick.time_msc / 1000.0 - utc_now) / 3600) * 3600)
วิธีนี้มีจุดอ่อนสามข้อ ข้อแรก เดมอนที่รันยาวข้ามวันเปลี่ยนเวลาฤดูร้อนจะถือ offset ค่าเก่าต่อไป ข้อมูลทั้งวันหลังจากนั้นเลื่อนไปหนึ่งชั่วโมงแบบเงียบ ๆ ข้อสอง เวลาดึงข้อมูลย้อนหลัง วันที่ย้อนไปดึงอาจอยู่คนละฤดูกับวันนี้ offset ของวันนี้เลยใช้กับวันนั้นไม่ได้ ข้อสาม ถ้าโปรแกรมเริ่มตอนที่ต้นทางหยุดส่ง tick ล่าสุดคือ tick ค้างของวันศุกร์ ส่วนต่างที่วัดได้ไม่ใช่ offset แต่เป็นระยะเวลาที่ต้นทางหยุดส่งมาแล้ว
ผมเคยเขียนกฎเปลี่ยนเวลาเองด้วยมือ คือหาวันที่เปลี่ยนเวลาของแต่ละปีแล้วเลือก 7200 หรือ 10800 ซึ่งทำงานได้ แต่เป็นโค้ดที่ผมต้องดูแลเองทั้งที่ระบบปฏิบัติการมีฐานข้อมูลเขตเวลาให้อยู่แล้ว เวอร์ชันที่ใช้อยู่ตอนนี้คำนวณ offset ต่อวันจาก ZoneInfo โดยถามที่จุดกึ่งกลางของวันทำการนั้น
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
SRV_TZ = ZoneInfo(settings['SOURCE_TZ']) # โซนเวลาของแหล่งข้อมูล อ่านจากค่าตั้งต่อโบรก ห้ามปล่อยให้เป็นค่า default
def day_offset(day_id):
"""offset (วินาที) ของวันทำการหนึ่งวัน วันทำการของชุดข้อมูลนี้เริ่ม 22:00 UTC"""
mid = datetime.fromtimestamp(day_id * 86400 - 7200 + 43200, tz=timezone.utc)
return int(mid.astimezone(SRV_TZ).utcoffset().total_seconds())
เวลาดึงย้อนหลังหลายวัน ผมเดินทีละวัน แต่ละวันใช้ offset ของวันนั้นเอง แล้วตัดผลลัพธ์ให้เหลือเฉพาะช่วง UTC ที่ขอจริงอีกชั้น กันกรณีที่คณิตศาสตร์เขตเวลาล้นขอบมาหนึ่งชั่วโมง
สำหรับงานสดที่ต้องรู้ offset ของขณะนี้ ผมยังวัดจาก tick อยู่ แต่เปลี่ยนกติกาว่า tick ที่ใช้เป็นหลักฐานได้ต้องเป็น tick ที่เวลาขยับระหว่างการสุ่มสองครั้งเท่านั้น tick ที่ค่าไม่เปลี่ยนถือว่าค้าง ไม่นับ และต้องมีอย่างน้อยสองสัญลักษณ์ให้ค่าตรงกัน ถ้ามีสัญลักษณ์เดียวก็ต้องเห็นค่าเดิมซ้ำสองรอบ แล้วค่าที่ยืนยันแล้วจะถูกเขียนลงไฟล์แยกตามเซิร์ฟเวอร์ เพื่อให้การเริ่มโปรแกรมช่วงสุดสัปดาห์มีค่าที่ถูกใช้ตั้งแต่ต้น
ตารางนี้เป็นของโบรก A ไม่ใช่กฎสากล
เรื่องที่ผมอยากให้คนอ่านระวังที่สุดคือ อย่าเอาตารางข้างบนไปใช้ตรง ๆ โดยไม่วัดเอง เพราะในงานของผมเองก็มีหลักฐานที่ขัดกันอยู่ ตอนต่อกับ terminal ของโบรก B ผมวัดเวลาของ tick ล่าสุดได้นำหน้า UTC อยู่ 3 ชั่วโมง ทั้งที่กับโบรก A ฟังก์ชันตระกูล tick คืน UTC และเอกสารของไลบรารีก็เขียนว่าเป็น UTC ส่วนโบรกอีกรายหนึ่งตั้งนาฬิกาเซิร์ฟเวอร์เป็น UTC ตรง ๆ offset เป็นศูนย์ ทุกฟังก์ชันเลยดูเหมือนถูกหมด จนกว่าจะย้ายโค้ดชุดเดียวกันไปต่อกับโบรกอื่น
ผมยังไม่ได้ไล่วัดครบทั้ง 8 ฟังก์ชันกับโบรก B เลยไม่สรุปว่าต่างกันตรงไหนบ้าง ที่สรุปได้มีข้อเดียวคือ เขตเวลาของ API ชุดนี้ขึ้นกับ terminal และเซิร์ฟเวอร์ที่ต่ออยู่ด้วย ไม่ได้ขึ้นกับไลบรารีอย่างเดียว
ตัวเก็บข้อมูลของผมอ่านเขตเวลาของเซิร์ฟเวอร์จากตัวแปรสภาพแวดล้อม และมีค่า default เป็นเขตเวลาของโบรกที่ใช้บ่อย วันที่ตัวเรียกโปรแกรมทำตัวแปรนี้หาย โปรแกรมไม่พัง มันแค่ใช้ค่า default กับ terminal ของโบรกที่นาฬิกาเป็น UTC ซึ่งถ้าปล่อยให้เขียนลงคลังจะได้ tick ที่เร็วไป 3 ชั่วโมงทุกแถว ผมเลยเพิ่มด่านว่าเขตเวลาที่ตั้งไว้ต้องตรงกับเซิร์ฟเวอร์ที่ต่ออยู่จริง ถ้าไม่ตรงให้ตัวเก็บข้อมูลปิดตัวเอง ไม่ใช่เดาต่อ
ด่านตรวจที่ควรมีในทุกโปรแกรมที่ต่อ API ชุดนี้
บั๊กทั้งหมดในเรื่องนี้มีลักษณะเดียวกันคือไม่โยน error สิ่งที่ช่วยได้คือการตรวจความสมเหตุสมผลของเวลาที่จุดเข้า ก่อนข้อมูลจะไหลลงคลัง ตัวอย่างข้างล่างเป็นแนวทางที่ผมสรุปจากอาการทั้งสี่แบบ เขียนสั้นมาก แต่ละบรรทัดผูกกับบั๊กหนึ่งแบบ
import time
def sanity_check(bar_utc_ts, tick_utc_ts, open_age, tf_sec=60):
now = time.time()
# แท่งล่าสุดต้องไม่อยู่ในอนาคต และไม่เก่าเกินสองแท่งตอนที่ข้อมูลกำลังวิ่ง
assert bar_utc_ts <= now + 5, f'เวลาแท่งอยู่ในอนาคต {bar_utc_ts - now:.0f}s'
# tick กับแท่งล่าสุดต้องอยู่ห่างกันไม่เกินหนึ่งแท่ง
assert abs(tick_utc_ts - bar_utc_ts) <= 2 * tf_sec, 'tick กับแท่งอยู่คนละเขตเวลา'
# อายุของรายการที่เปิดค้างเป็นลบไม่ได้
assert open_age >= 0, f'อายุติดลบ {open_age:.0f}s = ลืมลบ offset'
# ส่วนต่างที่เป็นจำนวนชั่วโมงเต็มคือลายเซ็นของบั๊กเขตเวลา
drift = round(bar_utc_ts - tick_utc_ts)
assert drift % 3600 != 0 or drift == 0, f'เพี้ยน {drift // 3600} ชั่วโมงพอดี'
ข้อสุดท้ายคือตัวที่ผมชอบที่สุด ความคลาดเคลื่อนที่เป็นจำนวนชั่วโมงเต็มพอดีแทบไม่มีทางเกิดจากความหน่วงของเครือข่ายหรือนาฬิกาเครื่องเดิน เกือบทุกครั้งคือเขตเวลา เห็นเลข 3600 7200 หรือ 10800 เมื่อไรให้หยุดหาสาเหตุอื่นก่อน
ด่านพวกนี้ต้องรันเฉพาะตอนที่ข้อมูลกำลังวิ่งจริง ช่วงที่ต้นทางหยุดส่ง tick ล่าสุดจะเก่าเป็นวันโดยชอบธรรม ด่านที่เทียบกับนาฬิกาปัจจุบันเลยควรข้ามไปเมื่อ tick ไม่ขยับระหว่างการสุ่มสองครั้ง ใช้กติกาเดียวกับตอนวัด offset
ตัวเลขของงานนี้
สรุปคือ ผมเสียเวลากับเรื่องนี้เพราะพยายามหา "เขตเวลาของ API" ทั้งที่ของแบบนั้นไม่มี มีแต่เขตเวลาของแต่ละฟังก์ชัน แยกขาเข้ากับขาออก และผูกกับโบรกที่ต่ออยู่ สิ่งที่เอาไปใช้ต่อได้คือวิธีวัด ไม่ใช่ตัวตาราง ส่วนตัวผมจะวัดใหม่ทุกครั้งที่เปลี่ยนโบรกหรือ terminal อัปเดตรุ่นใหญ่ แล้วเก็บผลไว้คู่กับโค้ด ใครมีผลวัดกับโบรกอื่นที่ไม่ตรงกับตารางนี้ก็เป็นเรื่องปกติครับ ไม่ได้แปลว่าใครวัดผิด ส่วนแถว history_orders_get ที่ผมยังไม่ได้วัดขาออกเอง กับผลของโบรก B ที่ยังวัดไม่ครบ เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ
เคยเจองานแบบนี้ไหม? ติดตรงไหน?
มาแลกวิธีกันต่อในบอร์ด LinuxThai



ความคิดเห็น 0
ยังไม่มีความคิดเห็น — เป็นคนแรกเลย