Cloud Firestore
Cloud Firestore: ابزاری قدرتمند برای معاملات آتی کریپتو
Cloud Firestore یک پایگاه داده NoSQL ابری است که توسط گوگل کلود ارائه شده و به دلیل ویژگیهای منحصر به فرد خود، به ابزاری محبوب در توسعه برنامههای کاربردی تبدیل شده است. این پایگاه داده به ویژه برای برنامههایی که نیاز به دسترسی بلادرنگ و همگامسازی دادهها دارند، بسیار مناسب است. در حوزه معاملات آتی کریپتو، استفاده از Cloud Firestore میتواند مزایای قابل توجهی را به همراه داشته باشد.
معرفی Cloud Firestore
Cloud Firestore یک پایگاه داده مستند-محور است که دادهها را در قالب مستندات و مجموعهها ذخیره میکند. این ساختار انعطافپذیر، امکان ذخیرهسازی و بازیابی دادهها را به شیوهای ساده و کارآمد فراهم میکند. یکی از ویژگیهای کلیدی Cloud Firestore، پشتیبانی از همگامسازی بلادرنگ است، به این معنا که هر گونه تغییر در دادهها به طور خودکار به تمامی کلاینتهای متصل ارسال میشود. این ویژگی برای برنامههای معاملاتی که نیاز به نمایش دادههای بهروز و دقیق دارند، بسیار مفید است.
مزایای استفاده از Cloud Firestore در معاملات آتی کریپتو
در حوزه معاملات آتی کریپتو، سرعت و دقت در دسترسی به دادهها از اهمیت بالایی برخوردار است. Cloud Firestore با ارائه دسترسی بلادرنگ به دادهها، امکان تصمیمگیری سریع و آگاهانه را برای معاملهگران فراهم میکند. برخی از مزایای کلیدی استفاده از Cloud Firestore در این حوزه عبارتند از:
- **همگامسازی بلادرنگ**: این ویژگی امکان بهروزرسانی دادهها در زمان واقعی را فراهم میکند، که برای نمایش قیمتها و وضعیت معاملات بسیار حیاتی است.
- **مقیاسپذیری**: Cloud Firestore به طور خودکار منابع مورد نیاز را بر اساس حجم دادهها و ترافیک کاربران مقیاس میدهد، که برای پلتفرمهای معاملاتی با کاربران زیاد بسیار مناسب است.
- **امنیت**: این پایگاه داده از مکانیزمهای امنیتی پیشرفته برای محافظت از دادهها استفاده میکند، که برای ذخیرهسازی اطلاعات حساس معاملاتی ضروری است.
- **سادگی در استفاده**: با استفاده از Cloud Firestore، توسعهدهندگان میتوانند به سرعت و بدون نیاز به مدیریت زیرساختهای پیچیده، برنامههای کاربردی خود را ایجاد و گسترش دهند.
=== نحوه استفاده از Cloud Firestore در معاملات آ# 1. 数据结构和算法
- 1.1 把序列分解为单独的变量
```
- 问题:有一个包含N个元素的元组或序列,现在将它分解为N个单独的变量。
- 解决方案
- 任何序列,或可迭代的对象都可以通过一个简单的赋值操作来分解为单独的变量。
- 唯一的要求是变量的总数和结构要与序列相吻合。
- 例如:
p = (4, 5) x, y = p print(x) # 4 print(y) # 5
data = ['ACME', 50, 91.1, (2012, 12, 21)] name, shares, price, date = data print(name) # ACME print(date) # (2012, 12, 21)
name, shares, price, (year, mon, day) = data print(name) # ACME print(year) # 2012 print(mon) # 12 print(day) # 21
- 如果元素的数量不匹配,将得到一个错误提示。例如:
- p = (4, 5)
- x, y, z = p
- ValueError: not enough values to unpack (expected 3, got 2)
- 讨论
- 实际上不仅仅只是元组或列表,只要对象是可迭代的,那么就可以执行分解操作。
- 这包括字符串、文件、迭代器以及生成器。比如:
s = 'Hello' a, b, c, d, e = s print(a) # H print(b) # e print(e) # o
- 当做分解操作时,有时候可能想丢弃某些特定的值。Python并没有提供特殊的语法
- 来实现这一点,但是通常可以使用一个用不到的变量名,以此来作为要丢弃的值的名称。
- 例如:
data = ['ACME', 50, 91.1, (2012, 12, 21)] _, shares, price, _ = data print(shares) # 50 print(price) # 91.1 ```
- 1.2 从任意长度的可迭代对象中分解元素
```
- 问题:需要从某个可迭代对象中分解出N个元素,但是这个可迭代对象的长度可能超过N,
- 这会导致出现分解值过多的异常(too many values to unpack)。
- 解决方案
- Python的 *表达式 可以用来解决这个问题。例如,假设开设了一门课程,并决定在
- 期末的作业成绩中去掉第一个和最后一个,只对中间剩下的成绩做平均分统计。
- 如果只有4个成绩,也许可以简单地将4个都分解出来,但是如果有24个呢?
- *表达式 使这一切都变得简单:
def drop_first_last(grades):
first, *middle, last = grades return sum(middle) / len(middle)
print(drop_first_last([1, 2, 3, 4])) # 2.5
- 另一个用例是假设有一些成绩记录,记录由姓名和成绩组成,现在想对它们进一步处理
records = [
('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4),
]
def do_foo(x, y):
print('foo', x, y)
def do_bar(s):
print('bar', s)
for tag, *args in records:
if tag == 'foo': do_foo(*args) elif tag == 'bar': do_bar(*args)
- 在拆分中,*表达式 在迭代一个变长的元组序列时尤其有用。例如:
records = [
('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4),
]
for tag, *args in records:
print(*args) # 1 2 # hello # 3 4
- *表达式 在字符串拆分时也非常有用。例如:
line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false' uname, *fields, homedir, sh = line.split(':') print(uname) # nobody print(homedir) # /var/empty print(sh) # /usr/bin/false
- 有时候可能想分解出某些值然后丢弃它们。在分解的时候,不能只使用一个单独的 * ,
- 但是可以使用几个常用来表示待丢弃值的变量名,比如 _ 或者 ign(ignored)。例如:
record = ('ACME', 50, 123.45, (12, 18, 2012)) name, *_, (*_, year) = record print(name) # ACME print(year) # 2012
- *表达式 在递归中的应用。例如:
def sum(items):
head, *tail = items return head + sum(tail) if tail else head
items = [1, 10, 7, 4, 5, 9] print(sum(items)) # 36
- 讨论
- 对于分解未知或任意长度的可迭代对象,这种扩展的分解操作可谓是量身定做的工具。
- 通常,这类可迭代对象中会有一些已知的组件或模式(例如,元素1之后的所有内容都
- 是电话号码),利用 *表达式 分解可迭代对象,使得开发者能够轻松地利用这些模式,
- 而不必在可迭代对象中做复杂的操作,才能得到相关的元素。
- *表达式 在迭代一个变长的元组序列时尤其有用。
```
- 1.3 保存最后N个元素
```
- 问题:希望在迭代或是其他形式的处理过程中对最后几项记录做一个有限的历史记录统计。
- 解决方案
- 保存有限的历史记录可算是 collections.deque 的完美应用场景了。例如,下面的代码对
- 一系列文本行做简单的文本匹配统计,当发现有匹配时就输出当前的匹配行以及最后检查过的N行文本。
from collections import deque
def search(lines, pattern, history=5):
previous_lines = deque(maxlen=history) for line in lines: if pattern in line: yield line, previous_lines previous_lines.append(line)
- Example use on a file
if __name__ == '__main__':
with open(r'../../cookbook/somefile.txt') as f: for line, prevlines in search(f, 'python', 5): for pline in prevlines: print(pline, end=) print(line, end=) print('-' * 20)
- 讨论
- 如同上面的代码片段中所做的一样,当编写搜索某项记录的代码时,通常会用到含有yield关键字的
- 生成器函数。这将处理搜索过程的代码和使用搜索结果的代码成功解耦开来。如果将来想展示更多
- 的上下文,只需要改变展示的步骤,而无需改变搜索的步骤。
- deque(maxlen=N) 创建了一个固定长度的队列。当有新记录加入而队列已满时会自动移除最老的那条记录。
q = deque(maxlen=3) q.append(1) q.append(2) q.append(3) print(q) # deque([1, 2, 3], maxlen=3) q.append(4) print(q) # deque([2, 3, 4], maxlen=3) q.append(5) print(q) # deque([3, 4, 5], maxlen=3)
- 尽管可以在列表上手动完成这样的操作(append、del),但队列这种解决方案要优雅得多,
- 运行速度也快得多。
- 更普遍的是,当需要一个简单的队列结构时,deque 可祝你一臂之力。如果不指定队列的大小,
- 也就得到了一个无界限的队列,可以在两端执行添加和弹出操作。
q = deque() q.append(1) q.append(2) q.append(3) print(q) # deque([1, 2, 3]) q.appendleft(4) print(q) # deque([4, 1, 2, 3]) q.pop() print(q) # deque([4, 1, 2]) q.popleft() print(q) # deque([1, 2])
- 从队列两端添加或弹出元素的复杂度都是O(1)。这和列表不同,当从列表的头部插入或移除
- 元素时,列表的复杂度为O(N)。
```
- 1.4 找到最大或最小的N个元素
```
- 问题:想在某个集合中找出最大或最小的N个元素。
- 解决方案
- heapq模块中有两个函数——nlargest()和nsmallest()——它们正是我们所需要的。例如:
import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] print(heapq.nlargest(3, nums)) # [42, 37, 23] print(heapq.nsmallest(3, nums)) # [-4, 1, 2]
- 这两个函数都可以接受一个参数key,从而允许它们工作在更加复杂的数据结构之上。例如:
portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1}, {'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}, {'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'ACME', 'shares': 75, 'price': 115.65}
] cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price']) expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price']) print(cheap)
- [{'name': 'YHOO', 'shares': 45, 'price': 16.35},
- {'name': 'FB', 'shares': 200, 'price': 21.09},
- {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
print(expensive)
- [{'name': 'AAPL', 'shares': 50, 'price': 543.22},
- {'name': 'ACME', 'shares': 75, 'price': 115.65},
- {'name': 'IBM', 'shares': 100, 'price': 91.1}]
- 如果只是简单的想找到最小或最大的元素(N=1时),那么使用min()和max()会更快。
- 同样,如果N和集合本身的大小差不多大,通常更快的方法是先对集合排序,然后做切片操作。
- (例如,使用sorted(items)[:N]或者sorted(items)[-N:])。应该要注意的是,nlargest()
- 和nsmallest()的实际实现会根据使用它们的方式而有所不同,可能会相应作出一些优化措施
- (比如,当N的大小和输入大小很接近时,就会采用排序的方法)。
- 讨论
- 如果正在寻找最大或最小的N个元素,且同集合中元素的总数目相比,N很小,那么以下这些函数
- 可以提供更好的性能。这些函数首先会在底层将数据转化成列表,且元素会以堆的顺序排列。例如:
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] import heapq heap = list(nums) heapq.heapify(heap) print(heap) # [-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]
- 堆最重要的特性就是heap[0]总是最小那个的元素。此外,接下来的元素可依次通过heapq.heappop()
- 方法轻松找到。该方法会将第一个元素(最小的)弹出,然后以第二小的元素取而代之(这个操作的
- 复杂度是O(logN),N代表堆的大小)。例如,要找到第三小的元素,可以这样做:
print(heapq.heappop(heap)) # -4 print(heapq.heappop(heap)) # 1 print(heapq.heappop(heap)) # 2
- 当所要找的元素数量相对较小时,函数nlargest()和nsmallest()才是最适用的。如果只是简单的
- 想找到最小或最大的元素(N=1时),那么使用min()和max()会更快。同样,如果N和集合本身
- 的大小差不多大,通常更快的方法是先对集合排序,然后做切片操作(例如,使用sorted(items)[:N]
- 或者sorted(items)[-N:])。应该要注意的是,nlargest()和nsmallest()的实际实现会根据使用
- 它们的方式而有所不同,可能会相应作出一些优化措施(比如,当N的大小和输入大小很接近时,就会
- 采用排序的方法)。
```
- 1.5 实现优先级队列
```
- 问题:想要实现一个队列,它能够以给定的优先级来对元素排序,且每次pop操作时都会返回优先级最高的那个元素。
- 解决方案
- 下面利用heapq模块实现了一个简单的优先级队列
import heapq
class PriorityQueue:
def __init__(self): self._queue = [] self._index = 0
def push(self, item, priority): heapq.heappush(self._queue, (-priority, self._index, item)) self._index += 1
def pop(self): return heapq.heappop(self._queue)[-1]
- 使用方式
class Item:
def __init__(self, name): self.name = name
def __repr__(self): return 'Item({!r})'.format(self.name)
q = PriorityQueue() q.push(Item('foo'), 1) q.push(Item('bar'), 5) q.push(Item('spam'), 4) q.push(Item('grok'), 1) print(q.pop()) # Item('bar') print(q.pop()) # Item('spam') print(q.pop()) # Item('foo') print(q.pop()) # Item('grok')
- 讨论
- 上面的代码片段核心在于heapq模块的使用。函数heapq.heappush()和heapq.heappop()分别实现
- 了将元素从列表_queue中插入和移除操作,且保证列表中第一个元素的优先级最低(1.4节讨论了
- 这是如何做到的)。heappop()方法总是返回“最小”的元素,因此这就是让队列能够弹出正确元素的关键。
- 此外,由于push和pop操作的复杂度都是O(logN),其中N代表堆中元素的数量,因此就算N的值很大,
- 这些操作的效率也会很高。
- 在这段代码中,队列以元组(-priority, index, item)的形式组成。把priority取负值是为了让队列
- 能够按照元素的优先级从高到低的顺序排列。这和正常的堆排列顺序相反,一般情况下堆是按从小到大的
- 顺序排序的。
```
- 1.6 在字典中将键映射到多个值上
```
- 问题:我们想要一个能将键(key)映射到多个值的字典(即所谓的一键多值字典[multidict])。
- 解决方案
- 字典是一种关联容器,每个键都映射到一个单独的值上。如果想让键映射到多个值,需要将这多个值保存到
- 另一个容器如列表或集合中。例如,可能会像这样创建字典:
d = {
'a' : [1, 2, 3], 'b' : [4, 5]
} e = {
'a' : {1, 2, 3}, 'b' : {4, 5}
}
- 要使用列表还是集合完全取决于应用的意图。如果希望保留元素插入的顺序,就用列表。如果希望消除
- 重复元素(且不在意它们的顺序),就用集合。
- 为了方便的创建这样的字典,可以使用collections模块中的defaultdict类。defaultdict的一个特点
- 就是它会自动初始化第一个值,这样只需关注添加元素即可。例如:
from collections import defaultdict
d = defaultdict(list) d['a'].append(1) d['a'].append(2) d['b'].append(4) print(d) # defaultdict(<class 'list'>, {'a': [1, 2], 'b': [4]})
d = defaultdict(set) d['a'].add(1) d['a'].add(2) d['b'].add(4) print(d) # defaultdict(<class 'set'>, {'a': {1, 2}, 'b': {4}})
- 关于defaultdict,需要注意的一个地方是,它会自动创建字典表项以待稍后的访问(即使这些表项当前在字典中还没有找到)。
- 如果不想要这个功能,可以在普通的字典上调用setdefault()方法来代替。例如:
d = {} # A regular dictionary d.setdefault('a', []).append(1) d.setdefault('a', []).append(2) d.setdefault('b', []).append(4) print(d) # {'a': [1, 2], 'b': [4]}
- 讨论
- 一般来说,构建一个一键多值字典是很容易的。但是如果试着自己对第一个值做初始化操作,这就会变得很杂乱。
- 例如,可能会写下这样的代码:
d = {} for key, value in pairs:
if key not in d: d[key] = [] d[key].append(value)
- 使用defaultdict后代码会清晰得多:
d = defaultdict(list) for key, value in pairs:
d[key].append(value)
```
- 1.7 让字典保持有序
```
- 问题:我们想要创建一个字典,同时当对字典做迭代或序列化操作时,也能控制其中元素的顺序。
- 解决方案
- 要控制字典中元素的顺序,可以使用collections模块中的OrderedDict类。当对字典做迭代时,它会严格按照元素初始添加的顺序进行。
- 例如:
from collections import OrderedDict
d = OrderedDict() d['foo'] = 1 d['bar'] = 2 d['spam'] = 3 d['grok'] = 4
- Outputs "foo 1", "bar 2", "spam 3", "grok 4"
for key in d:
print(key, d[key])
- OrderedDict 内部维护了一个双向链表,它会根据元素加入的顺序来排列键的位置。第一个新加入的元素被放置在链表的末尾。
- 接下来对已存在的键做重新赋值不会改变键的顺序。
- 需要注意的是,OrderedDict 的大小是普通字典的两倍多,这是由于它额外创建的链表所造成的。
- 因此,如果打算构建一个涉及大量 OrderedDict 实例的数据结构(例如从CSV文件中读取100000行内容到 OrderedDict 列表中),
- 那么需要认真对应用做需求分析,从而判断使用 OrderedDict 所带来的好处是否能超越因额外的内存开销所带来的缺点。
- 讨论
- OrderedDict 在需要保持字典顺序的场景下非常有用,例如在解析CSV文件时,可能需要保持列的顺序不变。
- 另外,在需要实现某些算法时,例如LRU缓存(最近最少使用)策略,OrderedDict 也能派上用场。
```
- 1.8 与字典有关的计算问题
```
- 问题:我们想在字典上对数据执行各式各样的计算(比如求最小值、最大值、排序等)。
- 解决方案
- 考虑下面的字典,股票名称和对应的价格:
prices = {
'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75
}
- 为了能对字典内容做些有用的计算,通常会利用zip()将字典的键和值反转过来。例如,下面的代码会找出最低和最高的股票价格
min_price = min(zip(prices.values(), prices.keys())) max_price = max(zip(prices.values(), prices.keys())) print(min_price) # (10.75, 'FB') print(max_price) # (612.78, 'AAPL')
- 类似地,要对数据排序只需要使用zip()再配合sorted()就可以了,比如:
prices_sorted = sorted(zip(prices.values(), prices.keys())) print(prices_sorted)
- [(10.75, 'FB'), (37.20, 'HPQ'), (45.23, 'ACME'), (205.55, 'IBM'), (612.78, 'AAPL')]
- 当进行这些计算时,请注意zip()创建了一个列表,它只能被消费一次。例如,下面的代码就是错误的:
prices_and_names = zip(prices.values(), prices.keys()) min_price = min(prices_and_names) # OK max_price = max(prices_and_names) # ValueError: max() arg is an empty sequence
- 讨论
- 如果尝试在字典上执行常见的数据操作,将会发现它们只会处理键,而不是值。例如:
min(prices) # Returns 'AAPL' max(prices) # Returns 'IBM'
- 这很可能不是我们所期望的,因为实际上我们是尝试对字典的值做计算。可以利用字典的values()方法来解决这个问题:
min(prices.values()) # Returns 10.75 max(prices.values()) # Returns 612.78
- 不幸的是,通常这也不是我们所期望的。比如,我们可能想知道相应的键所关联的信息是什么(比如哪只股票的价格最低?)
- 如果提供一个key参数传递给min()和max(),就能得到最大值和最小值所对应的键是什么。例如:
min_key = min(prices, key=lambda k: prices[k]) max_key = max(prices, key=lambda k: prices[k]) print(min_key) # 'FB' print(max_key) # 'AAPL'
- 但是,要得到最小值的话,还需要额外执行一次查找。例如:
min_value = prices[min(prices, key=lambda k: prices[k])] print(min_value) # 10.75
- 利用了zip()的解决方案是通过将字典的键-值对“反转”为值-键对序列来解决这个问题的。
- 当在这样的元组上执行比较操作时,值会先进行比较,然后才是键。这完全符合我们的期望,
- 允许我们用一条单独的语句轻松的对字典里的内容做整理和排序。
- 应该要注意的是,在计算(比如求最小值和最大值)时,如果碰巧value的值相同,则将返回拥有最小或最大key值的那个条目。
- 例如:
prices = {'AAA': 45.23, 'ZZZ': 45.23} min(zip(prices.values(), prices.keys())) # (45.23, 'AAA') max(zip(prices.values(), prices.keys())) # (45.23, 'ZZZ') ```
پلتفرمهای پیشنهادی معاملات آتی
پلتفرم | ویژگیهای آتی | ثبتنام |
---|---|---|
Binance Futures | اهرم تا 125 برابر، قراردادهای USDⓈ-M | همین حالا ثبتنام کنید |
Bybit Futures | قراردادهای دائمی معکوس | شروع معاملات |
BingX Futures | معاملات کپی برای آتی | به BingX بپیوندید |
Bitget Futures | قراردادهای با مارجین USDT | حساب باز کنید |
به جامعه بپیوندید
برای اطلاعات بیشتر در کانال تلگرام @strategybin اشتراک کنید. سودآورترین پلتفرم کریپتو - اینجا ثبتنام کنید.
در جامعه ما مشارکت کنید
برای تحلیلها، سیگنالهای رایگان و بیشتر، در کانال تلگرام @cryptofuturestrading اشتراک کنید!